| Directory: | ./ |
|---|---|
| File: | sql/item.cc |
| Date: | 2022-11-26 14:12:44 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 4699 | 5326 | 88.2% |
| Branches: | 3614 | 5659 | 63.9% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | Copyright (c) 2000, 2022, Oracle and/or its affiliates. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License, version 2.0, | ||
| 6 | as published by the Free Software Foundation. | ||
| 7 | |||
| 8 | This program is also distributed with certain software (including | ||
| 9 | but not limited to OpenSSL) that is licensed under separate terms, | ||
| 10 | as designated in a particular file or component or in included license | ||
| 11 | documentation. The authors of MySQL hereby grant you an additional | ||
| 12 | permission to link the program and your derivative works with the | ||
| 13 | separately licensed software that they have included with MySQL. | ||
| 14 | |||
| 15 | This program is distributed in the hope that it will be useful, | ||
| 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | GNU General Public License, version 2.0, for more details. | ||
| 19 | |||
| 20 | You should have received a copy of the GNU General Public License | ||
| 21 | along with this program; if not, write to the Free Software | ||
| 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ | ||
| 23 | |||
| 24 | #include "sql/item.h" | ||
| 25 | |||
| 26 | #include "integer_digits.h" | ||
| 27 | #include "my_compiler.h" | ||
| 28 | #include "my_config.h" | ||
| 29 | |||
| 30 | #include <stdio.h> | ||
| 31 | #ifdef HAVE_SYS_TIME_H | ||
| 32 | #include <sys/time.h> | ||
| 33 | #endif | ||
| 34 | #include <stddef.h> | ||
| 35 | #include <algorithm> | ||
| 36 | #include <optional> | ||
| 37 | #include <utility> | ||
| 38 | |||
| 39 | #include "decimal.h" | ||
| 40 | #include "float.h" | ||
| 41 | #include "limits.h" | ||
| 42 | #include "my_alloc.h" | ||
| 43 | #include "my_dbug.h" | ||
| 44 | #include "my_inttypes.h" | ||
| 45 | #include "my_macros.h" | ||
| 46 | #include "myisampack.h" // mi_int8store | ||
| 47 | #include "mysql.h" // IS_NUM | ||
| 48 | #include "mysql_time.h" | ||
| 49 | #include "sql-common/json_dom.h" // Json_wrapper | ||
| 50 | #include "sql/aggregate_check.h" // Distinct_check | ||
| 51 | #include "sql/auth/auth_acls.h" | ||
| 52 | #include "sql/auth/auth_common.h" // get_column_grant | ||
| 53 | #include "sql/auth/sql_security_ctx.h" | ||
| 54 | #include "sql/current_thd.h" | ||
| 55 | #include "sql/derror.h" // ER_THD | ||
| 56 | #include "sql/error_handler.h" // Internal_error_handler | ||
| 57 | #include "sql/gis/srid.h" | ||
| 58 | #include "sql/item_cmpfunc.h" // COND_EQUAL | ||
| 59 | #include "sql/item_create.h" // create_temporal_literal | ||
| 60 | #include "sql/item_func.h" // item_func_sleep_init | ||
| 61 | #include "sql/item_json_func.h" // json_value | ||
| 62 | #include "sql/item_row.h" | ||
| 63 | #include "sql/item_strfunc.h" // Item_func_conv_charset | ||
| 64 | #include "sql/item_subselect.h" | ||
| 65 | #include "sql/item_sum.h" // Item_sum | ||
| 66 | #include "sql/key.h" | ||
| 67 | #include "sql/log_event.h" // append_query_string | ||
| 68 | #include "sql/mysqld.h" // lower_case_table_names files_charset_info | ||
| 69 | #include "sql/protocol.h" | ||
| 70 | #include "sql/query_options.h" | ||
| 71 | #include "sql/select_lex_visitor.h" | ||
| 72 | #include "sql/sp.h" // sp_map_item_type | ||
| 73 | #include "sql/sp_rcontext.h" // sp_rcontext | ||
| 74 | #include "sql/sql_base.h" // view_ref_found | ||
| 75 | #include "sql/sql_bitmap.h" | ||
| 76 | #include "sql/sql_class.h" // THD | ||
| 77 | #include "sql/sql_derived.h" // Condition_pushdown | ||
| 78 | #include "sql/sql_error.h" | ||
| 79 | #include "sql/sql_lex.h" | ||
| 80 | #include "sql/sql_list.h" | ||
| 81 | #include "sql/sql_show.h" // append_identifier | ||
| 82 | #include "sql/sql_time.h" // Date_time_format | ||
| 83 | #include "sql/sql_view.h" // VIEW_ANY_ACL | ||
| 84 | #include "sql/system_variables.h" | ||
| 85 | #include "sql/thd_raii.h" | ||
| 86 | #include "sql/tztime.h" // my_tz_UTC | ||
| 87 | #include "template_utils.h" | ||
| 88 | #include "typelib.h" | ||
| 89 | #include "unsafe_string_append.h" | ||
| 90 | |||
| 91 | using std::max; | ||
| 92 | using std::min; | ||
| 93 | using std::string; | ||
| 94 | |||
| 95 | const String my_null_string("NULL", 4, default_charset_info); | ||
| 96 | |||
| 97 | /** | ||
| 98 | Alias from select list can be referenced only from ORDER BY (SQL Standard) or | ||
| 99 | from HAVING, GROUP BY and a subquery in the select list (MySQL extension). | ||
| 100 | |||
| 101 | We don't allow it be referenced from the SELECT list, with one exception: | ||
| 102 | it's accepted if nested in a subquery, which is inconsistent but necessary | ||
| 103 | as our users have shown to rely on this workaround. | ||
| 104 | */ | ||
| 105 | 552 | static inline bool select_alias_referencable(enum_parsing_context place) { | |
| 106 |
4/4✓ Branch 0 taken 197 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 39 times.
|
225 | return (place == CTX_SELECT_LIST || place == CTX_GROUP_BY || |
| 107 |
4/4✓ Branch 0 taken 225 times.
✓ Branch 1 taken 327 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 135 times.
|
777 | place == CTX_HAVING || place == CTX_ORDER_BY); |
| 108 | } | ||
| 109 | |||
| 110 | 144268 | Type_properties::Type_properties(Item &item) | |
| 111 | 144268 | : m_type(item.data_type()), | |
| 112 | 144268 | m_unsigned_flag(item.unsigned_flag), | |
| 113 | 144268 | m_max_length(item.max_length), | |
| 114 | 144268 | m_collation(item.collation) {} | |
| 115 | |||
| 116 | static enum_field_types real_data_type(Item *item); | ||
| 117 | |||
| 118 | /***************************************************************************** | ||
| 119 | ** Item functions | ||
| 120 | *****************************************************************************/ | ||
| 121 | |||
| 122 | /** | ||
| 123 | Init all special items. | ||
| 124 | */ | ||
| 125 | |||
| 126 | 12108 | void item_init(void) { | |
| 127 | 12108 | item_func_sleep_init(); | |
| 128 | 12108 | uuid_short_init(); | |
| 129 | 12108 | } | |
| 130 | |||
| 131 | 79484025 | Item::Item() | |
| 132 | 79484274 | : next_free(nullptr), | |
| 133 | 79484274 | str_value(), | |
| 134 | 79484320 | collation(&my_charset_bin, DERIVATION_COERCIBLE), | |
| 135 | 79484510 | item_name(), | |
| 136 | 79484375 | orig_name(), | |
| 137 | 79484631 | max_length(0), | |
| 138 | 79484631 | marker(MARKER_NONE), | |
| 139 | 79484631 | cmp_context(INVALID_RESULT), | |
| 140 | 79484631 | is_parser_item(false), | |
| 141 | 79484631 | is_expensive_cache(-1), | |
| 142 | 79484631 | m_data_type(MYSQL_TYPE_INVALID), | |
| 143 | 79484631 | fixed(false), | |
| 144 | 79484631 | decimals(0), | |
| 145 | 79484631 | m_nullable(false), | |
| 146 | 79484631 | null_value(false), | |
| 147 | 79484631 | unsigned_flag(false), | |
| 148 | 79484631 | m_is_window_function(false), | |
| 149 | 79484631 | derived_used(false), | |
| 150 | 79484025 | m_accum_properties(0) { | |
| 151 | #ifndef NDEBUG | ||
| 152 | 79484631 | contextualized = true; | |
| 153 | #endif // NDEBUG | ||
| 154 | |||
| 155 | // Put item into global list so that we can free all items at end | ||
| 156 |
2/4✓ Branch 0 taken 79484433 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79484357 times.
✗ Branch 3 not taken.
|
79484631 | current_thd->add_item(this); |
| 157 | 79484357 | } | |
| 158 | |||
| 159 | 2058993 | Item::Item(THD *thd, const Item *item) | |
| 160 | 2059000 | : next_free(nullptr), | |
| 161 | 2059000 | str_value(item->str_value), | |
| 162 | 2059003 | collation(item->collation), | |
| 163 | 2059003 | item_name(item->item_name), | |
| 164 | 2059003 | orig_name(item->orig_name), | |
| 165 | 2059003 | max_length(item->max_length), | |
| 166 | 2059003 | marker(MARKER_NONE), | |
| 167 | 2059003 | cmp_context(item->cmp_context), | |
| 168 | 2059003 | is_parser_item(false), | |
| 169 | 2059003 | is_expensive_cache(-1), | |
| 170 | 2059003 | m_data_type(item->data_type()), | |
| 171 | 2059007 | fixed(item->fixed), | |
| 172 | 2059007 | decimals(item->decimals), | |
| 173 | 2059007 | m_nullable(item->m_nullable), | |
| 174 | 2059007 | null_value(item->null_value), | |
| 175 | 2059007 | unsigned_flag(item->unsigned_flag), | |
| 176 | 2059007 | m_is_window_function(item->m_is_window_function), | |
| 177 | 2059007 | derived_used(item->derived_used), | |
| 178 | 2058993 | m_accum_properties(item->m_accum_properties) { | |
| 179 | #ifndef NDEBUG | ||
| 180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2059007 times.
|
2059007 | assert(item->contextualized); |
| 181 | 2059007 | contextualized = true; | |
| 182 | #endif // NDEBUG | ||
| 183 | |||
| 184 | // Add item to global list | ||
| 185 |
1/2✓ Branch 0 taken 2059000 times.
✗ Branch 1 not taken.
|
2059007 | thd->add_item(this); |
| 186 | 2059000 | } | |
| 187 | |||
| 188 | 353571063 | Item::Item(const POS &) | |
| 189 | 353571817 | : next_free(nullptr), | |
| 190 | 353571817 | str_value(), | |
| 191 | 353572060 | collation(&my_charset_bin, DERIVATION_COERCIBLE), | |
| 192 | 353572853 | item_name(), | |
| 193 | 353573145 | orig_name(), | |
| 194 | 353572862 | max_length(0), | |
| 195 | 353572862 | marker(MARKER_NONE), | |
| 196 | 353572862 | cmp_context(INVALID_RESULT), | |
| 197 | 353572862 | is_parser_item(true), | |
| 198 | 353572862 | is_expensive_cache(-1), | |
| 199 | 353572862 | m_data_type(MYSQL_TYPE_INVALID), | |
| 200 | 353572862 | fixed(false), | |
| 201 | 353572862 | decimals(0), | |
| 202 | 353572862 | m_nullable(false), | |
| 203 | 353572862 | null_value(false), | |
| 204 | 353572862 | unsigned_flag(false), | |
| 205 | 353572862 | m_is_window_function(false), | |
| 206 | 353572862 | derived_used(false), | |
| 207 | 353571063 | m_accum_properties(0) {} | |
| 208 | |||
| 209 | 9425909 | bool Item::may_eval_const_item(const THD *thd) const { | |
| 210 |
4/4✓ Branch 0 taken 138643 times.
✓ Branch 1 taken 9287272 times.
✓ Branch 2 taken 138620 times.
✓ Branch 3 taken 24 times.
|
9425909 | return !thd->lex->is_view_context_analysis() || basic_const_item(); |
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | @todo | ||
| 215 | Make this functions class dependent | ||
| 216 | */ | ||
| 217 | |||
| 218 | 332281737 | bool Item::val_bool() { | |
| 219 |
3/4✓ Branch 0 taken 332281679 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 312 times.
✗ Branch 3 not taken.
|
332281737 | switch (result_type()) { |
| 220 | 332281679 | case INT_RESULT: | |
| 221 | 332281679 | return val_int() != 0; | |
| 222 | 31 | case DECIMAL_RESULT: { | |
| 223 | 31 | my_decimal decimal_value; | |
| 224 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | my_decimal *val = val_decimal(&decimal_value); |
| 225 |
3/4✓ Branch 0 taken 25 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
|
31 | if (val) return !my_decimal_is_zero(val); |
| 226 | 6 | return false; | |
| 227 | 31 | } | |
| 228 | 312 | case REAL_RESULT: | |
| 229 | case STRING_RESULT: | ||
| 230 | 312 | return val_real() != 0.0; | |
| 231 | ✗ | case ROW_RESULT: | |
| 232 | default: | ||
| 233 | ✗ | assert(0); | |
| 234 | return false; // Wrong (but safe) | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | /* | ||
| 239 | For the items which don't have its own fast val_str_ascii() | ||
| 240 | implementation we provide a generic slower version, | ||
| 241 | which converts from the Item character set to ASCII. | ||
| 242 | For better performance conversion happens only in | ||
| 243 | case of a "tricky" Item character set (e.g. UCS2). | ||
| 244 | Normally conversion does not happen. | ||
| 245 | */ | ||
| 246 | 160760 | String *Item::val_str_ascii(String *str) { | |
| 247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 160760 times.
|
160760 | assert(str != &str_value); |
| 248 | |||
| 249 | uint errors; | ||
| 250 |
1/2✓ Branch 0 taken 160868 times.
✗ Branch 1 not taken.
|
160760 | String *res = val_str(&str_value); |
| 251 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 160789 times.
|
160868 | if (!res) return nullptr; |
| 252 | |||
| 253 |
2/2✓ Branch 0 taken 160404 times.
✓ Branch 1 taken 392 times.
|
160789 | if (!(res->charset()->state & MY_CS_NONASCII)) |
| 254 | 160404 | str = res; | |
| 255 | else { | ||
| 256 |
2/4✓ Branch 0 taken 403 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 397 times.
|
407 | if ((null_value = str->copy(res->ptr(), res->length(), collation.collation, |
| 257 | &my_charset_latin1, &errors))) | ||
| 258 | ✗ | return nullptr; | |
| 259 | } | ||
| 260 | 160801 | return str; | |
| 261 | } | ||
| 262 | |||
| 263 | 10 | String *Item::val_string_from_real(String *str) { | |
| 264 | 10 | double nr = val_real(); | |
| 265 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
|
10 | if (null_value) return nullptr; /* purecov: inspected */ |
| 266 | 3 | str->set_real(nr, decimals, &my_charset_bin); | |
| 267 | 3 | return str; | |
| 268 | } | ||
| 269 | |||
| 270 | 13 | String *Item::val_string_from_int(String *str) { | |
| 271 | 13 | longlong nr = val_int(); | |
| 272 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (null_value) return nullptr; |
| 273 | 13 | str->set_int(nr, unsigned_flag, &my_charset_bin); | |
| 274 | 13 | return str; | |
| 275 | } | ||
| 276 | |||
| 277 | 29188 | String *Item::val_string_from_decimal(String *str) { | |
| 278 |
1/2✓ Branch 0 taken 29188 times.
✗ Branch 1 not taken.
|
29188 | my_decimal dec_buf, *dec = val_decimal(&dec_buf); |
| 279 |
3/4✓ Branch 0 taken 1829 times.
✓ Branch 1 taken 27359 times.
✓ Branch 2 taken 1829 times.
✗ Branch 3 not taken.
|
29188 | if (null_value) return error_str(); |
| 280 |
1/2✓ Branch 0 taken 27359 times.
✗ Branch 1 not taken.
|
27359 | my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, false, &dec_buf); |
| 281 |
1/2✓ Branch 0 taken 27359 times.
✗ Branch 1 not taken.
|
27359 | my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, str); |
| 282 | 27359 | return str; | |
| 283 | 29188 | } | |
| 284 | |||
| 285 | 10931 | String *Item::val_string_from_datetime(String *str) { | |
| 286 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10931 times.
|
10931 | assert(fixed == 1); |
| 287 | MYSQL_TIME ltime; | ||
| 288 |
5/6✓ Branch 0 taken 10931 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2811 times.
✓ Branch 3 taken 8120 times.
✓ Branch 4 taken 8120 times.
✓ Branch 5 taken 2811 times.
|
13742 | if (get_date(<ime, TIME_FUZZY_DATE) || |
| 289 |
2/4✓ Branch 0 taken 2811 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2811 times.
|
2811 | (null_value = str->alloc(MAX_DATE_STRING_REP_LENGTH))) |
| 290 |
1/2✓ Branch 0 taken 8120 times.
✗ Branch 1 not taken.
|
8120 | return error_str(); |
| 291 |
1/2✓ Branch 0 taken 2811 times.
✗ Branch 1 not taken.
|
2811 | make_datetime((Date_time_format *)nullptr, <ime, str, decimals); |
| 292 | 2811 | return str; | |
| 293 | } | ||
| 294 | |||
| 295 | 69 | String *Item::val_string_from_date(String *str) { | |
| 296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | assert(fixed == 1); |
| 297 | MYSQL_TIME ltime; | ||
| 298 |
5/6✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 65 times.
|
134 | if (get_date(<ime, TIME_FUZZY_DATE) || |
| 299 |
2/4✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 65 times.
|
65 | (null_value = str->alloc(MAX_DATE_STRING_REP_LENGTH))) |
| 300 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | return error_str(); |
| 301 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | make_date((Date_time_format *)nullptr, <ime, str); |
| 302 | 65 | return str; | |
| 303 | } | ||
| 304 | |||
| 305 | 159 | String *Item::val_string_from_time(String *str) { | |
| 306 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 159 times.
|
159 | assert(fixed == 1); |
| 307 | MYSQL_TIME ltime; | ||
| 308 |
7/10✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 152 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 152 times.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 152 times.
|
159 | if (get_time(<ime) || (null_value = str->alloc(MAX_DATE_STRING_REP_LENGTH))) |
| 309 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | return error_str(); |
| 310 |
1/2✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
|
152 | make_time((Date_time_format *)nullptr, <ime, str, decimals); |
| 311 | 152 | return str; | |
| 312 | } | ||
| 313 | |||
| 314 | 38 | my_decimal *Item::val_decimal_from_real(my_decimal *decimal_value) { | |
| 315 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | DBUG_TRACE; |
| 316 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | double nr = val_real(); |
| 317 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37 times.
|
38 | if (null_value) return nullptr; |
| 318 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value); |
| 319 | 37 | return decimal_value; | |
| 320 | 38 | } | |
| 321 | |||
| 322 | 13346 | my_decimal *Item::val_decimal_from_int(my_decimal *decimal_value) { | |
| 323 | 13346 | longlong nr = val_int(); | |
| 324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13346 times.
|
13346 | if (null_value) return nullptr; |
| 325 | 13346 | int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value); | |
| 326 | 13346 | return decimal_value; | |
| 327 | } | ||
| 328 | |||
| 329 | 255 | my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value) { | |
| 330 | String *res; | ||
| 331 | |||
| 332 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
|
255 | if (!(res = val_str(&str_value))) return nullptr; |
| 333 | |||
| 334 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 207 times.
|
255 | if (str2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_BAD_NUM, res->ptr(), |
| 335 | res->length(), res->charset(), decimal_value)) { | ||
| 336 | /* | ||
| 337 | The EC_BAD_NUM message is awkward that's why we didn't let | ||
| 338 | str2my_decimal() send it above. We unconditionally send: | ||
| 339 | */ | ||
| 340 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | ErrConvString err(res); |
| 341 | 48 | push_warning_printf( | |
| 342 |
2/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
|
48 | current_thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE, |
| 343 |
2/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
|
48 | ER_THD(current_thd, ER_TRUNCATED_WRONG_VALUE), "DECIMAL", err.ptr()); |
| 344 | } | ||
| 345 | 255 | return decimal_value; | |
| 346 | } | ||
| 347 | |||
| 348 | 70 | my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value) { | |
| 349 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 | assert(fixed == 1); |
| 350 | MYSQL_TIME ltime; | ||
| 351 |
3/4✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 43 times.
|
70 | if (get_date(<ime, TIME_FUZZY_DATE)) { |
| 352 | 27 | return error_decimal(decimal_value); | |
| 353 | } | ||
| 354 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | return date2my_decimal(<ime, decimal_value); |
| 355 | } | ||
| 356 | |||
| 357 | 128 | my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value) { | |
| 358 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
|
128 | assert(fixed == 1); |
| 359 | MYSQL_TIME ltime; | ||
| 360 |
3/4✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 127 times.
|
128 | if (get_time(<ime)) { |
| 361 | 1 | return error_decimal(decimal_value); | |
| 362 | } | ||
| 363 |
1/2✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
|
127 | return date2my_decimal(<ime, decimal_value); |
| 364 | } | ||
| 365 | |||
| 366 | 99 | longlong Item::val_time_temporal() { | |
| 367 | MYSQL_TIME ltime; | ||
| 368 |
3/4✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 90 times.
|
99 | if ((null_value = get_time(<ime))) return 0; |
| 369 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | return TIME_to_longlong_time_packed(ltime); |
| 370 | } | ||
| 371 | |||
| 372 | 2429 | longlong Item::val_date_temporal() { | |
| 373 | MYSQL_TIME ltime; | ||
| 374 |
1/2✓ Branch 0 taken 2429 times.
✗ Branch 1 not taken.
|
2429 | const sql_mode_t mode = current_thd->variables.sql_mode; |
| 375 | 2429 | const my_time_flags_t flags = | |
| 376 | 2429 | TIME_FUZZY_DATE | (mode & MODE_INVALID_DATES ? TIME_INVALID_DATES : 0) | | |
| 377 | 2429 | (mode & MODE_NO_ZERO_IN_DATE ? TIME_NO_ZERO_IN_DATE : 0) | | |
| 378 | (mode & MODE_NO_ZERO_DATE ? TIME_NO_ZERO_DATE : 0); | ||
| 379 |
3/4✓ Branch 0 taken 2429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
✓ Branch 3 taken 2322 times.
|
2429 | if (get_date(<ime, flags)) return error_int(); |
| 380 |
1/2✓ Branch 0 taken 2322 times.
✗ Branch 1 not taken.
|
2322 | return TIME_to_longlong_datetime_packed(ltime); |
| 381 | } | ||
| 382 | |||
| 383 | // TS-TODO: split into separate methods? | ||
| 384 | 43 | longlong Item::val_temporal_with_round(enum_field_types type, uint8 dec) { | |
| 385 | 43 | longlong nr = val_temporal_by_field_type(); | |
| 386 | longlong diff = | ||
| 387 | 43 | my_time_fraction_remainder(my_packed_time_get_frac_part(nr), dec); | |
| 388 | 43 | longlong abs_diff = diff > 0 ? diff : -diff; | |
| 389 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
|
43 | if (abs_diff * 2 >= (int)log_10_int[DATETIME_MAX_DECIMALS - dec]) { |
| 390 | /* Needs rounding */ | ||
| 391 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | switch (type) { |
| 392 | ✗ | case MYSQL_TYPE_TIME: { | |
| 393 | MYSQL_TIME ltime; | ||
| 394 | ✗ | TIME_from_longlong_time_packed(<ime, nr); | |
| 395 | ✗ | return my_time_adjust_frac(<ime, dec, | |
| 396 | ✗ | current_thd->is_fsp_truncate_mode()) | |
| 397 | ✗ | ? 0 | |
| 398 | ✗ | : TIME_to_longlong_time_packed(ltime); | |
| 399 | } | ||
| 400 | 2 | case MYSQL_TYPE_TIMESTAMP: | |
| 401 | case MYSQL_TYPE_DATETIME: { | ||
| 402 | MYSQL_TIME ltime; | ||
| 403 | 2 | int warnings = 0; | |
| 404 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | TIME_from_longlong_datetime_packed(<ime, nr); |
| 405 | 6 | return propagate_datetime_overflow( | |
| 406 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | current_thd, &warnings, |
| 407 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | my_datetime_adjust_frac(<ime, dec, &warnings, |
| 408 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | current_thd->is_fsp_truncate_mode())) |
| 409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | ? 0 |
| 410 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | : TIME_to_longlong_datetime_packed(ltime); |
| 411 | return nr; | ||
| 412 | } | ||
| 413 | ✗ | default: | |
| 414 | ✗ | assert(0); | |
| 415 | break; | ||
| 416 | } | ||
| 417 | } | ||
| 418 | /* Does not need rounding, do simple truncation. */ | ||
| 419 | 41 | nr -= diff; | |
| 420 | 41 | return nr; | |
| 421 | } | ||
| 422 | |||
| 423 | 119 | double Item::val_real_from_decimal() { | |
| 424 | /* Note that fix_fields may not be called for Item_avg_field items */ | ||
| 425 | double result; | ||
| 426 |
1/2✓ Branch 0 taken 119 times.
✗ Branch 1 not taken.
|
119 | my_decimal value_buff, *dec_val = val_decimal(&value_buff); |
| 427 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 111 times.
|
119 | if (null_value) return 0.0; |
| 428 |
1/2✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
|
111 | my_decimal2double(E_DEC_FATAL_ERROR, dec_val, &result); |
| 429 | 111 | return result; | |
| 430 | 119 | } | |
| 431 | |||
| 432 | 34685 | double Item::val_real_from_string() { | |
| 433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34685 times.
|
34685 | assert(fixed); |
| 434 | 34685 | StringBuffer<STRING_BUFFER_USUAL_SIZE> tmp; | |
| 435 |
1/2✓ Branch 0 taken 34685 times.
✗ Branch 1 not taken.
|
34685 | const String *res = val_str(&tmp); |
| 436 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 34499 times.
|
34685 | if (res == nullptr) return 0.0; |
| 437 |
1/2✓ Branch 0 taken 34499 times.
✗ Branch 1 not taken.
|
34499 | return double_from_string_with_check(res->charset(), res->ptr(), |
| 438 | 68998 | res->ptr() + res->length()); | |
| 439 | 34685 | } | |
| 440 | |||
| 441 | 29 | longlong Item::val_int_from_decimal() { | |
| 442 | /* Note that fix_fields may not be called for Item_avg_field items */ | ||
| 443 | longlong result; | ||
| 444 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | my_decimal value, *dec_val = val_decimal(&value); |
| 445 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 26 times.
|
29 | if (null_value) return 0; |
| 446 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | my_decimal2int(E_DEC_FATAL_ERROR, dec_val, unsigned_flag, &result); |
| 447 | 26 | return result; | |
| 448 | 29 | } | |
| 449 | |||
| 450 | 65 | longlong Item::val_int_from_time() { | |
| 451 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
|
65 | assert(fixed == 1); |
| 452 | MYSQL_TIME ltime; | ||
| 453 | 65 | ulonglong value = 0; | |
| 454 |
3/4✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 62 times.
|
65 | if (get_time(<ime)) return 0LL; |
| 455 | |||
| 456 |
3/4✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 35 times.
|
62 | if (current_thd->is_fsp_truncate_mode()) |
| 457 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | value = TIME_to_ulonglong_time(ltime); |
| 458 | else | ||
| 459 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | value = TIME_to_ulonglong_time_round(ltime); |
| 460 | |||
| 461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | return (ltime.neg ? -1 : 1) * value; |
| 462 | } | ||
| 463 | |||
| 464 | 35 | longlong Item::val_int_from_date() { | |
| 465 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | assert(fixed == 1); |
| 466 | MYSQL_TIME ltime; | ||
| 467 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | return get_date(<ime, TIME_FUZZY_DATE) |
| 468 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
|
35 | ? 0LL |
| 469 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
35 | : (longlong)TIME_to_ulonglong_date(ltime); |
| 470 | } | ||
| 471 | |||
| 472 | 43 | longlong Item::val_int_from_datetime() { | |
| 473 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | assert(fixed == 1); |
| 474 | MYSQL_TIME ltime; | ||
| 475 |
2/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
|
43 | if (get_date(<ime, TIME_FUZZY_DATE)) return 0LL; |
| 476 | |||
| 477 |
2/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
|
43 | if (current_thd->is_fsp_truncate_mode()) |
| 478 | ✗ | return TIME_to_ulonglong_datetime(ltime); | |
| 479 | else { | ||
| 480 |
2/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
|
43 | return propagate_datetime_overflow(current_thd, [&](int *warnings) { |
| 481 | 43 | return TIME_to_ulonglong_datetime_round(ltime, warnings); | |
| 482 | 43 | }); | |
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 486 | 21 | longlong Item::val_int_from_string() { | |
| 487 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | assert(fixed); |
| 488 | 21 | StringBuffer<MY_INT64_NUM_DECIMAL_DIGITS + 1> tmp; | |
| 489 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | const String *res = val_str(&tmp); |
| 490 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 12 times.
|
21 | if (res == nullptr) return 0; |
| 491 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | return longlong_from_string_with_check( |
| 492 | 24 | res->charset(), res->ptr(), res->ptr() + res->length(), unsigned_flag); | |
| 493 | 21 | } | |
| 494 | |||
| 495 | 1428 | type_conversion_status Item::save_time_in_field(Field *field) { | |
| 496 | MYSQL_TIME ltime; | ||
| 497 |
4/6✓ Branch 0 taken 1428 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 1334 times.
✓ Branch 4 taken 94 times.
✗ Branch 5 not taken.
|
1428 | if (get_time(<ime)) return set_field_to_null_with_conversions(field, false); |
| 498 |
1/2✓ Branch 0 taken 1334 times.
✗ Branch 1 not taken.
|
1334 | field->set_notnull(); |
| 499 |
1/2✓ Branch 0 taken 1334 times.
✗ Branch 1 not taken.
|
1334 | return field->store_time(<ime, decimals); |
| 500 | } | ||
| 501 | |||
| 502 | 10060 | type_conversion_status Item::save_date_in_field(Field *field) { | |
| 503 | MYSQL_TIME ltime; | ||
| 504 | 10060 | my_time_flags_t flags = TIME_FUZZY_DATE; | |
| 505 |
1/2✓ Branch 0 taken 10060 times.
✗ Branch 1 not taken.
|
10060 | const sql_mode_t mode = current_thd->variables.sql_mode; |
| 506 |
2/2✓ Branch 0 taken 4441 times.
✓ Branch 1 taken 5619 times.
|
10060 | if (mode & MODE_INVALID_DATES) flags |= TIME_INVALID_DATES; |
| 507 |
3/4✓ Branch 0 taken 10060 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1748 times.
✓ Branch 3 taken 8312 times.
|
10060 | if (get_date(<ime, flags)) |
| 508 |
1/2✓ Branch 0 taken 1748 times.
✗ Branch 1 not taken.
|
1748 | return set_field_to_null_with_conversions(field, false); |
| 509 |
1/2✓ Branch 0 taken 8312 times.
✗ Branch 1 not taken.
|
8312 | field->set_notnull(); |
| 510 |
1/2✓ Branch 0 taken 8312 times.
✗ Branch 1 not taken.
|
8312 | return field->store_time(<ime, decimals); |
| 511 | } | ||
| 512 | |||
| 513 | /* | ||
| 514 | Store the string value in field directly | ||
| 515 | |||
| 516 | SYNOPSIS | ||
| 517 | Item::save_str_value_in_field() | ||
| 518 | field a pointer to field where to store | ||
| 519 | result the pointer to the string value to be stored | ||
| 520 | |||
| 521 | DESCRIPTION | ||
| 522 | The method is used by Item_*::save_in_field_inner() implementations | ||
| 523 | when we don't need to calculate the value to store | ||
| 524 | See Item_string::save_in_field_inner() implementation for example | ||
| 525 | |||
| 526 | IMPLEMENTATION | ||
| 527 | Check if the Item is null and stores the NULL or the | ||
| 528 | result value in the field accordingly. | ||
| 529 | |||
| 530 | RETURN | ||
| 531 | Nonzero value if error | ||
| 532 | */ | ||
| 533 | |||
| 534 | 20663740 | type_conversion_status Item::save_str_value_in_field(Field *field, | |
| 535 | String *result) { | ||
| 536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20663740 times.
|
20663740 | if (null_value) return set_field_to_null(field); |
| 537 | |||
| 538 | 20663740 | field->set_notnull(); | |
| 539 | 20663902 | return field->store(result->ptr(), result->length(), collation.collation); | |
| 540 | } | ||
| 541 | |||
| 542 | /** | ||
| 543 | Aggregates data types from array of items into current item | ||
| 544 | |||
| 545 | @param items array of items to aggregate the type from | ||
| 546 | |||
| 547 | This function aggregates all type information from the array of items. | ||
| 548 | Found type is supposed to be used later as the result data type | ||
| 549 | of a multi-argument function. | ||
| 550 | Aggregation itself is performed partially by the Field::field_type_merge() | ||
| 551 | function. | ||
| 552 | */ | ||
| 553 | |||
| 554 | 8785653 | void Item::aggregate_type(Bounds_checked_array<Item *> items) { | |
| 555 | 8785653 | uint itemno = 0; | |
| 556 | 8785653 | const uint count = items.size(); | |
| 557 |
6/6✓ Branch 0 taken 12213222 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 3427627 times.
✓ Branch 3 taken 8785595 times.
✓ Branch 4 taken 3427627 times.
✓ Branch 5 taken 8785653 times.
|
12213280 | while (itemno < count && items[itemno]->data_type() == MYSQL_TYPE_NULL) |
| 558 | 3427627 | itemno++; | |
| 559 | |||
| 560 |
2/2✓ Branch 0 taken 58 times.
✓ Branch 1 taken 8785595 times.
|
8785653 | if (itemno == count) // All items have NULL type, consolidated type is NULL |
| 561 | { | ||
| 562 | 58 | set_data_type(MYSQL_TYPE_NULL); | |
| 563 | 58 | return; | |
| 564 | } | ||
| 565 | |||
| 566 |
2/4✓ Branch 0 taken 8785595 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8785595 times.
|
8785595 | assert(items[itemno]->result_type() != ROW_RESULT); |
| 567 | |||
| 568 |
1/2✓ Branch 0 taken 8785595 times.
✗ Branch 1 not taken.
|
8785595 | enum_field_types new_type = real_data_type(items[itemno]); |
| 569 | 8785595 | uint8 new_dec = items[itemno]->decimals; | |
| 570 | 8785595 | bool new_unsigned = items[itemno]->unsigned_flag; | |
| 571 | 8785595 | bool mixed_signs = false; | |
| 572 | |||
| 573 |
2/2✓ Branch 0 taken 7441758 times.
✓ Branch 1 taken 8785595 times.
|
16227353 | for (itemno = itemno + 1; itemno < count; itemno++) { |
| 574 | // Do not aggregate items with NULL type | ||
| 575 |
2/2✓ Branch 0 taken 517955 times.
✓ Branch 1 taken 6923803 times.
|
7441758 | if (items[itemno]->data_type() == MYSQL_TYPE_NULL) continue; |
| 576 |
2/4✓ Branch 0 taken 6923803 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6923803 times.
|
6923803 | assert(items[itemno]->result_type() != ROW_RESULT); |
| 577 |
2/4✓ Branch 0 taken 6923803 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6923803 times.
✗ Branch 3 not taken.
|
6923803 | new_type = Field::field_type_merge(new_type, real_data_type(items[itemno])); |
| 578 | 6923803 | mixed_signs |= (new_unsigned != items[itemno]->unsigned_flag); | |
| 579 | 6923803 | new_dec = max<uint8>(new_dec, items[itemno]->decimals); | |
| 580 | } | ||
| 581 |
6/6✓ Branch 0 taken 1916411 times.
✓ Branch 1 taken 6869184 times.
✓ Branch 2 taken 1891968 times.
✓ Branch 3 taken 24443 times.
✓ Branch 4 taken 1891968 times.
✓ Branch 5 taken 6893627 times.
|
8785595 | if (mixed_signs && is_integer_type(new_type)) { |
| 582 | 1891968 | bool bump_range = false; | |
| 583 |
2/2✓ Branch 0 taken 3787784 times.
✓ Branch 1 taken 1891968 times.
|
5679752 | for (uint i = 0; i < count; i++) |
| 584 |
4/4✓ Branch 0 taken 1891970 times.
✓ Branch 1 taken 1895814 times.
✓ Branch 2 taken 520 times.
✓ Branch 3 taken 1891450 times.
|
5680274 | bump_range |= (items[i]->unsigned_flag && |
| 585 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 518 times.
|
1892490 | (items[i]->data_type() == new_type || |
| 586 | 520 | items[i]->data_type() == MYSQL_TYPE_BIT)); | |
| 587 |
2/2✓ Branch 0 taken 1891450 times.
✓ Branch 1 taken 518 times.
|
1891968 | if (bump_range) { |
| 588 |
5/6✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1891429 times.
✗ Branch 5 not taken.
|
1891450 | switch (new_type) { |
| 589 | 5 | case MYSQL_TYPE_TINY: | |
| 590 | 5 | new_type = MYSQL_TYPE_SHORT; | |
| 591 | 5 | break; | |
| 592 | 4 | case MYSQL_TYPE_SHORT: | |
| 593 | 4 | new_type = MYSQL_TYPE_INT24; | |
| 594 | 4 | break; | |
| 595 | 4 | case MYSQL_TYPE_INT24: | |
| 596 | 4 | new_type = MYSQL_TYPE_LONG; | |
| 597 | 4 | break; | |
| 598 | 8 | case MYSQL_TYPE_LONG: | |
| 599 | 8 | new_type = MYSQL_TYPE_LONGLONG; | |
| 600 | 8 | break; | |
| 601 | 1891429 | case MYSQL_TYPE_LONGLONG: | |
| 602 | 1891429 | new_type = MYSQL_TYPE_NEWDECIMAL; | |
| 603 | 1891429 | break; | |
| 604 | ✗ | default: | |
| 605 | ✗ | break; | |
| 606 | } | ||
| 607 | } | ||
| 608 | } | ||
| 609 | |||
| 610 | 8785595 | set_data_type(real_type_to_type(new_type)); | |
| 611 | 8785595 | decimals = new_dec; | |
| 612 |
4/4✓ Branch 0 taken 2677214 times.
✓ Branch 1 taken 6108381 times.
✓ Branch 2 taken 824400 times.
✓ Branch 3 taken 1852814 times.
|
8785595 | unsigned_flag = new_unsigned && !mixed_signs; |
| 613 | 8785595 | max_length = 0; | |
| 614 | 8785595 | return; | |
| 615 | } | ||
| 616 | |||
| 617 | 353956324 | bool Item::itemize(Parse_context *pc, Item **res) { | |
| 618 |
2/2✓ Branch 0 taken 408352 times.
✓ Branch 1 taken 353548149 times.
|
353956324 | if (skip_itemize(res)) return false; |
| 619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 353550203 times.
|
353548149 | if (super::contextualize(pc)) return true; |
| 620 | |||
| 621 | // Add item to global list | ||
| 622 | 353550203 | pc->thd->add_item(this); | |
| 623 | /* | ||
| 624 | Item constructor can be called during execution other then SQL_COM | ||
| 625 | command => we should check pc->select on zero | ||
| 626 | */ | ||
| 627 |
1/2✓ Branch 0 taken 353549664 times.
✗ Branch 1 not taken.
|
353549597 | if (pc->select) { |
| 628 | 353549664 | enum_parsing_context place = pc->select->parsing_place; | |
| 629 |
4/4✓ Branch 0 taken 163803079 times.
✓ Branch 1 taken 189746585 times.
✓ Branch 2 taken 71760 times.
✓ Branch 3 taken 163731319 times.
|
353549664 | if (place == CTX_SELECT_LIST || place == CTX_HAVING) |
| 630 | 189818345 | pc->select->select_n_having_items++; | |
| 631 | } | ||
| 632 | 353549597 | return false; | |
| 633 | } | ||
| 634 | |||
| 635 | 8734727 | uint Item::decimal_precision() const { | |
| 636 | 8734727 | Item_result restype = result_type(); | |
| 637 | 8734740 | constexpr const uint DATE_INT_DIGITS{8}; /* YYYYMMDD */ | |
| 638 | 8734740 | constexpr const uint TIME_INT_DIGITS{7}; /* hhhmmss */ | |
| 639 | 8734740 | constexpr const uint DATETIME_INT_DIGITS{14}; /* YYYYMMDDhhmmss */ | |
| 640 | |||
| 641 |
4/4✓ Branch 0 taken 7832615 times.
✓ Branch 1 taken 902125 times.
✓ Branch 2 taken 7777073 times.
✓ Branch 3 taken 55542 times.
|
8734740 | if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) { |
| 642 | 8679200 | uint prec = my_decimal_length_to_precision(max_char_length(), decimals, | |
| 643 |
1/2✓ Branch 0 taken 8679200 times.
✗ Branch 1 not taken.
|
8679198 | unsigned_flag); |
| 644 | 8679199 | return max<uint>(1, min<uint>(prec, DECIMAL_MAX_PRECISION)); | |
| 645 | } | ||
| 646 |
4/4✓ Branch 0 taken 112 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 55121 times.
|
55542 | switch (data_type()) { |
| 647 | 112 | case MYSQL_TYPE_TIME: | |
| 648 | 112 | return decimals + TIME_INT_DIGITS; | |
| 649 | 285 | case MYSQL_TYPE_DATETIME: | |
| 650 | case MYSQL_TYPE_TIMESTAMP: | ||
| 651 | 285 | return decimals + DATETIME_INT_DIGITS; | |
| 652 | 24 | case MYSQL_TYPE_DATE: | |
| 653 | 24 | return decimals + DATE_INT_DIGITS; | |
| 654 | 55121 | default: | |
| 655 | 55121 | break; | |
| 656 | } | ||
| 657 |
1/2✓ Branch 0 taken 55121 times.
✗ Branch 1 not taken.
|
55121 | return min<uint>(max_char_length(), DECIMAL_MAX_PRECISION); |
| 658 | } | ||
| 659 | |||
| 660 | 35418 | uint Item::time_precision() { | |
| 661 |
2/2✓ Branch 0 taken 761 times.
✓ Branch 1 taken 560 times.
|
36739 | if (!current_thd->lex->is_view_context_analysis() && const_item() && |
| 662 |
8/8✓ Branch 0 taken 1321 times.
✓ Branch 1 taken 34097 times.
✓ Branch 2 taken 714 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 705 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 705 times.
✓ Branch 7 taken 34713 times.
|
36739 | result_type() == STRING_RESULT && !is_temporal()) { |
| 663 | MYSQL_TIME ltime; | ||
| 664 | 705 | String buf, *tmp; | |
| 665 | 705 | MYSQL_TIME_STATUS status; | |
| 666 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 705 times.
|
705 | assert(fixed); |
| 667 | // Nanosecond rounding is not needed, for performance purposes | ||
| 668 |
5/6✓ Branch 0 taken 705 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 698 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 691 times.
✓ Branch 5 taken 14 times.
|
1403 | if ((tmp = val_str(&buf)) && |
| 669 |
3/4✓ Branch 0 taken 698 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 691 times.
✓ Branch 3 taken 7 times.
|
698 | str_to_time(tmp, <ime, TIME_FRAC_TRUNCATE, &status) == 0) |
| 670 | 691 | return min(status.fractional_digits, uint{DATETIME_MAX_DECIMALS}); | |
| 671 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 691 times.
|
705 | } |
| 672 | 34727 | return min(decimals, uint8{DATETIME_MAX_DECIMALS}); | |
| 673 | } | ||
| 674 | |||
| 675 | 304163 | uint Item::datetime_precision() { | |
| 676 |
2/2✓ Branch 0 taken 179635 times.
✓ Branch 1 taken 117228 times.
|
601026 | if (!current_thd->lex->is_view_context_analysis() && const_item() && |
| 677 |
8/8✓ Branch 0 taken 296863 times.
✓ Branch 1 taken 7300 times.
✓ Branch 2 taken 179586 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 179581 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 179581 times.
✓ Branch 7 taken 124582 times.
|
601026 | result_type() == STRING_RESULT && !is_temporal()) { |
| 678 | MYSQL_TIME ltime; | ||
| 679 | 179581 | String buf, *tmp; | |
| 680 | 179581 | MYSQL_TIME_STATUS status; | |
| 681 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 179581 times.
|
179581 | assert(fixed); |
| 682 | // Nanosecond rounding is not needed, for performance purposes | ||
| 683 |
5/6✓ Branch 0 taken 179581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✓ Branch 3 taken 179103 times.
✓ Branch 4 taken 471 times.
✓ Branch 5 taken 179110 times.
|
180059 | if ((tmp = val_str(&buf)) && |
| 684 |
2/2✓ Branch 0 taken 471 times.
✓ Branch 1 taken 7 times.
|
478 | !propagate_datetime_overflow( |
| 685 |
1/2✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
|
478 | current_thd, &status.warnings, |
| 686 |
2/4✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478 times.
✗ Branch 3 not taken.
|
478 | str_to_datetime(tmp, <ime, TIME_FRAC_TRUNCATE | TIME_FUZZY_DATE, |
| 687 | &status))) | ||
| 688 | 471 | return min(status.fractional_digits, uint{DATETIME_MAX_DECIMALS}); | |
| 689 |
2/2✓ Branch 0 taken 179110 times.
✓ Branch 1 taken 471 times.
|
179581 | } |
| 690 | 303692 | return min(decimals, uint8{DATETIME_MAX_DECIMALS}); | |
| 691 | } | ||
| 692 | |||
| 693 | 2940729 | void Item::print_item_w_name(const THD *thd, String *str, | |
| 694 | enum_query_type query_type) const { | ||
| 695 | 2940729 | print(thd, str, query_type); | |
| 696 | |||
| 697 |
3/6✓ Branch 0 taken 2940730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2940730 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2940730 times.
✗ Branch 5 not taken.
|
2940730 | if (item_name.is_set() && query_type != QT_NORMALIZED_FORMAT) { |
| 698 | 2940730 | str->append(STRING_WITH_LEN(" AS ")); | |
| 699 | 2940729 | append_identifier(thd, str, item_name.ptr(), item_name.length()); | |
| 700 | } | ||
| 701 | 2940730 | } | |
| 702 | |||
| 703 | /** | ||
| 704 | @details | ||
| 705 | "SELECT (subq) GROUP BY (same_subq)" confuses ONLY_FULL_GROUP_BY (it does | ||
| 706 | not see that both subqueries are the same, raises an error). | ||
| 707 | To avoid hitting this problem, if the original query was: | ||
| 708 | "SELECT expression AS x GROUP BY x", we print "GROUP BY x", not | ||
| 709 | "GROUP BY expression". Same for ORDER BY. | ||
| 710 | This has practical importance for views created as | ||
| 711 | "CREATE VIEW v SELECT (subq) AS x GROUP BY x" | ||
| 712 | (print_order() is used to write the view's definition in the frm file). | ||
| 713 | We make one exception: if the view is merge-able, its ORDER clause will be | ||
| 714 | merged into the parent query's. If an identifier in the merged ORDER clause | ||
| 715 | is allowed to be either an alias or an expression of the view's underlying | ||
| 716 | tables, resolution is difficult: it may be to be found in the underlying | ||
| 717 | tables of the view, or in the SELECT list of the view; unlike other ORDER | ||
| 718 | elements directly originating from the parent query. | ||
| 719 | To avoid this problem, if the view is merge-able, we print the | ||
| 720 | expression. This does not cause problems with only_full_group_by, because a | ||
| 721 | merge-able view never has GROUP BY. @see mysql_register_view(). | ||
| 722 | */ | ||
| 723 | 291866 | void Item::print_for_order(const THD *thd, String *str, | |
| 724 | enum_query_type query_type, bool used_alias) const { | ||
| 725 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 291812 times.
|
291866 | if ((query_type & QT_NORMALIZED_FORMAT) != 0) |
| 726 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | str->append("?"); |
| 727 |
2/2✓ Branch 0 taken 50359 times.
✓ Branch 1 taken 241453 times.
|
291812 | else if (used_alias) { |
| 728 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50359 times.
|
50359 | assert(item_name.is_set()); |
| 729 | // In the clause, user has referenced expression using an alias; we use it | ||
| 730 | 50359 | append_identifier(thd, str, item_name.ptr(), item_name.length()); | |
| 731 | } else { | ||
| 732 |
5/6✓ Branch 0 taken 9 times.
✓ Branch 1 taken 241444 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 241444 times.
|
241453 | if (type() == Item::INT_ITEM && basic_const_item()) { |
| 733 | /* | ||
| 734 | "ORDER BY N" means "order by the N-th element". To avoid such | ||
| 735 | interpretation we write "ORDER BY ''", which is equivalent. | ||
| 736 | */ | ||
| 737 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | str->append("''"); |
| 738 | } else | ||
| 739 | 241444 | print(thd, str, query_type); | |
| 740 | } | ||
| 741 | 291866 | } | |
| 742 | |||
| 743 | 3336 | bool Item::visitor_processor(uchar *arg) { | |
| 744 | 3336 | Select_lex_visitor *visitor = pointer_cast<Select_lex_visitor *>(arg); | |
| 745 | 3336 | return visitor->visit(this); | |
| 746 | } | ||
| 747 | |||
| 748 | /** | ||
| 749 | rename item (used for views, cleanup() return original name). | ||
| 750 | |||
| 751 | @param new_name new name of item; | ||
| 752 | */ | ||
| 753 | |||
| 754 | 9840206 | void Item::rename(char *new_name) { | |
| 755 | /* | ||
| 756 | we can compare pointers to names here, because if name was not changed, | ||
| 757 | pointer will be same | ||
| 758 | */ | ||
| 759 |
3/6✓ Branch 0 taken 9840219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9840221 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9840223 times.
✗ Branch 5 not taken.
|
9840206 | if (!orig_name.is_set() && new_name != item_name.ptr()) orig_name = item_name; |
| 760 | 9840221 | item_name.set(new_name); | |
| 761 | 9840225 | } | |
| 762 | |||
| 763 | 237349 | Item *Item::transform(Item_transformer transformer, uchar *arg) { | |
| 764 |
1/2✓ Branch 0 taken 237349 times.
✗ Branch 1 not taken.
|
237349 | return (this->*transformer)(arg); |
| 765 | } | ||
| 766 | |||
| 767 | 70123035 | bool Item_ident::itemize(Parse_context *pc, Item **res) { | |
| 768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70123241 times.
|
70123035 | if (skip_itemize(res)) return false; |
| 769 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70123541 times.
|
70123241 | if (super::itemize(pc, res)) return true; |
| 770 | 70123541 | context = pc->thd->lex->current_context(); | |
| 771 | 70123427 | return false; | |
| 772 | } | ||
| 773 | |||
| 774 | 4 | bool Item::check_function_as_value_generator(uchar *checker_args) { | |
| 775 | Check_function_as_value_generator_parameters *func_arg = | ||
| 776 | 4 | pointer_cast<Check_function_as_value_generator_parameters *>( | |
| 777 | checker_args); | ||
| 778 | 4 | Item_func *func_item = nullptr; | |
| 779 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
|
4 | if (type() == Item::FUNC_ITEM && |
| 780 | ✗ | ((func_item = down_cast<Item_func *>(this)))) { | |
| 781 | ✗ | func_arg->banned_function_name = func_item->func_name(); | |
| 782 | } | ||
| 783 | 4 | func_arg->err_code = func_arg->get_unnamed_function_error_code(); | |
| 784 | 4 | return true; | |
| 785 | } | ||
| 786 | |||
| 787 | ✗ | bool Item_ident::update_depended_from(uchar *arg) { | |
| 788 | ✗ | auto *info = pointer_cast<Item_ident::Depended_change *>(arg); | |
| 789 | ✗ | if (depended_from == info->old_depended_from) | |
| 790 | ✗ | depended_from = info->new_depended_from; | |
| 791 | ✗ | return false; | |
| 792 | } | ||
| 793 | |||
| 794 | /** | ||
| 795 | Store the pointer to this item field into a list if not already there. | ||
| 796 | |||
| 797 | The method is used by Item::walk to collect all unique Item_field objects | ||
| 798 | from a tree of Items into a set of items represented as a list. | ||
| 799 | |||
| 800 | Item_cond::walk() and Item_func::walk() stop the evaluation of the | ||
| 801 | processor function for its arguments once the processor returns | ||
| 802 | true.Therefore in order to force this method being called for all item | ||
| 803 | arguments in a condition the method must return false. | ||
| 804 | |||
| 805 | @param arg pointer to a mem_root_deque<Item_field *> | ||
| 806 | |||
| 807 | @return | ||
| 808 | false to force the evaluation of collect_item_field_processor | ||
| 809 | for the subsequent items. | ||
| 810 | */ | ||
| 811 | |||
| 812 | 1687575 | bool Item_field::collect_item_field_processor(uchar *arg) { | |
| 813 |
1/2✓ Branch 0 taken 1687575 times.
✗ Branch 1 not taken.
|
1687575 | DBUG_TRACE; |
| 814 |
6/10✓ Branch 0 taken 1687575 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1687575 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 1687566 times.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
|
1687575 | DBUG_PRINT("info", ("%s", field_name ? field_name : "noname")); |
| 815 | 1687575 | mem_root_deque<Item_field *> *item_list = | |
| 816 | reinterpret_cast<mem_root_deque<Item_field *> *>(arg); | ||
| 817 |
7/12✓ Branch 0 taken 1687575 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1687575 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1315124 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 970329 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2657904 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1315124 times.
✓ Branch 11 taken 1342780 times.
|
2657904 | for (Item_field *curr_item : *item_list) { |
| 818 |
3/4✓ Branch 0 taken 1315124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 344795 times.
✓ Branch 3 taken 970329 times.
|
1315124 | if (curr_item->eq(this, true)) return false; /* Already in the set. */ |
| 819 | } | ||
| 820 |
1/2✓ Branch 0 taken 1342780 times.
✗ Branch 1 not taken.
|
1342780 | item_list->push_back(this); |
| 821 | 1342780 | return false; | |
| 822 | 1687575 | } | |
| 823 | |||
| 824 | ✗ | bool Item_field::collect_item_field_or_ref_processor(uchar *arg) { | |
| 825 | ✗ | auto *info = pointer_cast<Collect_item_fields_or_refs *>(arg); | |
| 826 | ✗ | if (info->is_stopped(this)) return false; | |
| 827 | |||
| 828 | ✗ | List_iterator<Item> item_list_it(*info->m_items); | |
| 829 | Item *curr_item; | ||
| 830 | ✗ | while ((curr_item = item_list_it++)) { | |
| 831 | ✗ | if (curr_item->eq(this, true)) return false; /* Already in the set. */ | |
| 832 | } | ||
| 833 | ✗ | info->m_items->push_back(this); | |
| 834 | ✗ | return false; | |
| 835 | } | ||
| 836 | |||
| 837 | 12 | bool Item_field::collect_item_field_or_view_ref_processor(uchar *arg) { | |
| 838 | 12 | auto *info = pointer_cast<Collect_item_fields_or_view_refs *>(arg); | |
| 839 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (info->is_stopped(this)) return false; |
| 840 | |||
| 841 | ✗ | List_iterator<Item> item_list_it(*info->m_item_fields_or_view_refs); | |
| 842 | Item *curr_item; | ||
| 843 | ✗ | while ((curr_item = item_list_it++)) { | |
| 844 | ✗ | if (curr_item->eq(this, true)) return false; /* Already in the set. */ | |
| 845 | } | ||
| 846 | ✗ | info->m_item_fields_or_view_refs->push_back(this); | |
| 847 | ✗ | return false; | |
| 848 | } | ||
| 849 | |||
| 850 | 661 | bool Item_field::add_field_to_set_processor(uchar *arg) { | |
| 851 |
1/2✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
|
661 | DBUG_TRACE; |
| 852 |
3/10✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 661 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 661 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
661 | DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname")); |
| 853 | 661 | TABLE *table = (TABLE *)arg; | |
| 854 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 414 times.
|
661 | if (table_ref->table == table) |
| 855 | 247 | bitmap_set_bit(&table->tmp_set, field->field_index()); | |
| 856 | 661 | return false; | |
| 857 | 661 | } | |
| 858 | |||
| 859 | 6896603 | bool Item_field::add_field_to_cond_set_processor(uchar *) { | |
| 860 |
1/2✓ Branch 0 taken 6896615 times.
✗ Branch 1 not taken.
|
6896603 | DBUG_TRACE; |
| 861 |
6/10✓ Branch 0 taken 6896611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6896606 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 6896600 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
|
6896615 | DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname")); |
| 862 | 6896606 | bitmap_set_bit(&field->table->cond_set, field->field_index()); | |
| 863 | 6896618 | return false; | |
| 864 | 6896595 | } | |
| 865 | |||
| 866 | 15922845 | bool Item_field::remove_column_from_bitmap(uchar *argument) { | |
| 867 | 15922845 | MY_BITMAP *bitmap = reinterpret_cast<MY_BITMAP *>(argument); | |
| 868 | 15922845 | bitmap_clear_bit(bitmap, field->field_index()); | |
| 869 | 15922845 | return false; | |
| 870 | } | ||
| 871 | |||
| 872 | /** | ||
| 873 | Check if an Item_field references some field from a list of fields. | ||
| 874 | |||
| 875 | Check whether the Item_field represented by 'this' references any | ||
| 876 | of the fields in the keyparts passed via 'arg'. Used with the | ||
| 877 | method Item::walk() to test whether any keypart in a sequence of | ||
| 878 | keyparts is referenced in an expression. | ||
| 879 | |||
| 880 | @param arg Field being compared, arg must be of type Field | ||
| 881 | |||
| 882 | @retval | ||
| 883 | true if 'this' references the field 'arg' | ||
| 884 | @retval | ||
| 885 | false otherwise | ||
| 886 | */ | ||
| 887 | |||
| 888 | 16 | bool Item_field::find_item_in_field_list_processor(uchar *arg) { | |
| 889 | 16 | KEY_PART_INFO *first_non_group_part = *((KEY_PART_INFO **)arg); | |
| 890 | 16 | KEY_PART_INFO *last_part = *(((KEY_PART_INFO **)arg) + 1); | |
| 891 | KEY_PART_INFO *cur_part; | ||
| 892 | |||
| 893 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | for (cur_part = first_non_group_part; cur_part != last_part; cur_part++) { |
| 894 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (field->eq(cur_part->field)) return true; |
| 895 | } | ||
| 896 | ✗ | return false; | |
| 897 | } | ||
| 898 | |||
| 899 | 120557 | bool Item_field::is_valid_for_pushdown(uchar *arg) { | |
| 900 | Condition_pushdown::Derived_table_info *dti = | ||
| 901 | 120557 | pointer_cast<Condition_pushdown::Derived_table_info *>(arg); | |
| 902 | 120557 | TABLE_LIST *derived_table = dti->m_derived_table; | |
| 903 |
2/2✓ Branch 0 taken 118420 times.
✓ Branch 1 taken 2137 times.
|
120557 | if (table_ref == derived_table) { |
| 904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 118420 times.
|
118420 | assert(field->table == derived_table->table); |
| 905 | // If the expression in the derived table for this column has a subquery | ||
| 906 | // or has non-deterministic result or is a trigger field, condition is | ||
| 907 | // not pushed down. | ||
| 908 | // Expressions having subqueries need a more complicated replacement | ||
| 909 | // strategy than the one that currently exists when the condition is | ||
| 910 | // moved to derived table. | ||
| 911 | // TODO: Lift this limitation. | ||
| 912 | // Any condition with expressions having non-deterministic result in the | ||
| 913 | // underlying derived table should not be pushed. | ||
| 914 | // For ex: | ||
| 915 | // select * from (select rand() as a from t1) where a >0.5; | ||
| 916 | // Here a > 0.5 if pushed down would result in rand() getting evaluated | ||
| 917 | // twice because the query would then be | ||
| 918 | // select * from (select rand() as a from t1 where rand() > 0.5) which | ||
| 919 | // is not correct. | ||
| 920 | // Trigger fields need complicated resolving when we clone a condition | ||
| 921 | // having them. | ||
| 922 | // Expressions which have system variables in the underlying derived | ||
| 923 | // table cannot be pushed as of now because Item_func_get_system_var::print | ||
| 924 | // does not print the original expression which leads to an incorrect clone. | ||
| 925 | Query_expression *derived_query_expression = | ||
| 926 | 118420 | derived_table->derived_query_expression(); | |
| 927 | 118420 | for (Query_block *qb = derived_query_expression->first_query_block(); | |
| 928 |
2/2✓ Branch 0 taken 118881 times.
✓ Branch 1 taken 118409 times.
|
237290 | qb != nullptr; qb = qb->next_query_block()) { |
| 929 |
1/2✓ Branch 0 taken 118881 times.
✗ Branch 1 not taken.
|
118881 | Item *item = qb->get_derived_expr(field->field_index()); |
| 930 | 118881 | bool has_trigger_field = false; | |
| 931 | 118881 | bool has_system_var = false; | |
| 932 |
1/2✓ Branch 0 taken 118881 times.
✗ Branch 1 not taken.
|
118881 | WalkItem(item, enum_walk::PREFIX, |
| 933 | 119719 | [&has_trigger_field, &has_system_var](Item *inner_item) { | |
| 934 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 119719 times.
|
119719 | if (inner_item->type() == Item::TRIGGER_FIELD_ITEM) { |
| 935 | ✗ | has_trigger_field = true; | |
| 936 | ✗ | return true; | |
| 937 | } | ||
| 938 |
3/4✓ Branch 0 taken 355 times.
✓ Branch 1 taken 119364 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 119719 times.
|
120074 | if (inner_item->type() == Item::FUNC_ITEM && |
| 939 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | down_cast<Item_func *>(inner_item)->functype() == |
| 940 | Item_func::GSYSVAR_FUNC) { | ||
| 941 | ✗ | has_system_var = true; | |
| 942 | ✗ | return true; | |
| 943 | } | ||
| 944 | 119719 | return false; | |
| 945 | }); | ||
| 946 |
4/6✓ Branch 0 taken 118876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118870 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 118870 times.
✗ Branch 5 not taken.
|
237757 | if (item->has_subquery() || item->is_non_deterministic() || |
| 947 |
5/6✓ Branch 0 taken 118876 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118870 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 118870 times.
|
237757 | has_trigger_field || has_system_var) |
| 948 | 11 | return true; | |
| 949 | } | ||
| 950 | 118409 | return false; | |
| 951 | } | ||
| 952 | 2137 | return true; | |
| 953 | } | ||
| 954 | |||
| 955 | /** | ||
| 956 | Check if this column is found in PARTITION clause of all the window functions. | ||
| 957 | Called when checking to see if a condition can be pushed past window functions | ||
| 958 | while pushing conditions down to materialized derived tables. | ||
| 959 | |||
| 960 | @param arg derived table | ||
| 961 | |||
| 962 | @retval | ||
| 963 | false if this field is part of PARTITION clause of all window functions | ||
| 964 | present in the derived table. | ||
| 965 | @retval | ||
| 966 | true otherwise | ||
| 967 | */ | ||
| 968 | |||
| 969 | 66 | bool Item_field::check_column_in_window_functions(uchar *arg) { | |
| 970 | 66 | Query_block *query_block = pointer_cast<Query_block *>(arg); | |
| 971 | // Find the expression corresponding to this column in derived table's | ||
| 972 | // query block and use that to find in window functions of that | ||
| 973 | // query block. | ||
| 974 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | Item *item = query_block->get_derived_expr(field->field_index()); |
| 975 | 66 | bool ret = true; | |
| 976 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | List_iterator<Window> li(query_block->m_windows); |
| 977 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 47 times.
|
125 | for (Window *w = li++; w != nullptr; w = li++) { |
| 978 | 78 | ret = true; | |
| 979 |
3/4✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 19 times.
|
109 | for (ORDER *o = w->first_partition_by(); o != nullptr; o = o->next) { |
| 980 | 90 | Item *expr = *(o->item); | |
| 981 |
6/8✓ Branch 0 taken 31 times.
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31 times.
✓ Branch 6 taken 59 times.
✓ Branch 7 taken 31 times.
|
90 | if (expr == item || item->eq(expr, false)) { |
| 982 | 59 | ret = false; | |
| 983 | 59 | break; | |
| 984 | } | ||
| 985 | } | ||
| 986 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 59 times.
|
78 | if (ret) return ret; |
| 987 | } | ||
| 988 | 47 | return ret; | |
| 989 | } | ||
| 990 | |||
| 991 | /** | ||
| 992 | Check if this column is found in GROUP BY. | ||
| 993 | Called when checking to see if a condition can be pushed past GROUP BY | ||
| 994 | while pushing conditions down to materialized derived tables. | ||
| 995 | |||
| 996 | @param arg derived table | ||
| 997 | |||
| 998 | @retval | ||
| 999 | false if this field is not part of GROUP BY. | ||
| 1000 | @retval | ||
| 1001 | true otherwise. | ||
| 1002 | */ | ||
| 1003 | 87 | bool Item_field::check_column_in_group_by(uchar *arg) { | |
| 1004 | 87 | Query_block *query_block = pointer_cast<Query_block *>(arg); | |
| 1005 | // Find the expression corresponding to this column in the derived | ||
| 1006 | // table's query block and use that to find in GROUP BY of that | ||
| 1007 | // query block. | ||
| 1008 | 87 | Item *item = query_block->get_derived_expr(field->field_index()); | |
| 1009 |
2/2✓ Branch 0 taken 99 times.
✓ Branch 1 taken 24 times.
|
123 | for (ORDER *group = query_block->group_list.first; group; |
| 1010 | 36 | group = group->next) { | |
| 1011 |
5/6✓ Branch 0 taken 36 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 63 times.
✓ Branch 5 taken 36 times.
|
99 | if (*group->item == item || item->eq(*group->item, false)) return false; |
| 1012 | } | ||
| 1013 | 24 | return true; | |
| 1014 | } | ||
| 1015 | |||
| 1016 | 118093 | Item *Item_field::replace_with_derived_expr(uchar *arg) { | |
| 1017 | Condition_pushdown::Derived_table_info *dti = | ||
| 1018 | 118093 | pointer_cast<Condition_pushdown::Derived_table_info *>(arg); | |
| 1019 | |||
| 1020 | // This column's table reference should be same as the derived table from | ||
| 1021 | // where the replacement is retrieved. If not, it is presumed that the | ||
| 1022 | // column has already been replaced with derived table expression (Maybe | ||
| 1023 | // there was an earlier reference to the same column in the condition that | ||
| 1024 | // is being pushed down). There is no need to do anything in such a case. | ||
| 1025 | 118093 | TABLE_LIST *derived_table = dti->m_derived_table; | |
| 1026 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 118093 times.
|
118093 | if (derived_table != table_ref) return this; |
| 1027 | 118093 | Query_block *query_block = dti->m_derived_query_block; | |
| 1028 | 118093 | return query_block->clone_expression( | |
| 1029 | 236186 | current_thd, query_block->get_derived_expr(field->field_index()), | |
| 1030 |
2/2✓ Branch 0 taken 117989 times.
✓ Branch 1 taken 104 times.
|
236082 | (derived_table->is_system_view || |
| 1031 |
2/2✓ Branch 0 taken 203 times.
✓ Branch 1 taken 117786 times.
|
117989 | (derived_table->referencing_view && |
| 1032 |
2/2✓ Branch 0 taken 197 times.
✓ Branch 1 taken 6 times.
|
118296 | derived_table->referencing_view->is_system_view))); |
| 1033 | } | ||
| 1034 | |||
| 1035 | 59 | Item *Item_field::replace_with_derived_expr_ref(uchar *arg) { | |
| 1036 | Condition_pushdown::Derived_table_info *dti = | ||
| 1037 | 59 | pointer_cast<Condition_pushdown::Derived_table_info *>(arg); | |
| 1038 | |||
| 1039 | // This column's table reference should be same as the derived table from | ||
| 1040 | // where the replacement is retrieved. If not, it is presumed that the | ||
| 1041 | // column has already been replaced with derived table expression (Maybe | ||
| 1042 | // there was an earlier reference to the same column in the condition that | ||
| 1043 | // is being pushed down). There is no need to do anything in such a case. | ||
| 1044 | 59 | TABLE_LIST *derived_table = dti->m_derived_table; | |
| 1045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (derived_table != table_ref) return this; |
| 1046 | 59 | Query_block *query_block = dti->m_derived_query_block; | |
| 1047 | |||
| 1048 | // Get the expression in the derived table and find the right ref item to | ||
| 1049 | // point to. | ||
| 1050 | 59 | Item *select_item = query_block->get_derived_expr(field->field_index()); | |
| 1051 | 59 | Item *new_ref = nullptr; | |
| 1052 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | if (select_item) { |
| 1053 | 59 | uint counter = 0; | |
| 1054 | enum_resolution_type resolution; | ||
| 1055 |
3/6✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
|
59 | if (find_item_in_list(current_thd, select_item, |
| 1056 | query_block->get_fields_list(), &counter, | ||
| 1057 | REPORT_EXCEPT_NOT_FOUND, &resolution)) { | ||
| 1058 | 59 | Item **replace_item = &query_block->base_ref_items[counter]; | |
| 1059 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
118 | new_ref = new Item_ref(&query_block->context, replace_item, nullptr, |
| 1060 | 59 | nullptr, (*replace_item)->item_name.ptr(), | |
| 1061 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
118 | resolution == RESOLVED_AGAINST_ALIAS); |
| 1062 | } | ||
| 1063 | } | ||
| 1064 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | assert(new_ref); |
| 1065 | 59 | return new_ref; | |
| 1066 | } | ||
| 1067 | |||
| 1068 | 102145 | bool Item_field::check_function_as_value_generator(uchar *checker_args) { | |
| 1069 | Check_function_as_value_generator_parameters *func_args = | ||
| 1070 | 102145 | pointer_cast<Check_function_as_value_generator_parameters *>( | |
| 1071 | checker_args); | ||
| 1072 | // We walk through the Item tree twice to check for disallowed functions; | ||
| 1073 | // once before resolving is done and once after resolving is done. Before | ||
| 1074 | // resolving is done, we don't have the field object available, and hence | ||
| 1075 | // the nullptr check. | ||
| 1076 |
2/2✓ Branch 0 taken 9820 times.
✓ Branch 1 taken 92325 times.
|
102145 | if (field == nullptr) { |
| 1077 | 9820 | return false; | |
| 1078 | } | ||
| 1079 | |||
| 1080 | 92325 | int fld_idx = func_args->col_index; | |
| 1081 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92325 times.
|
92325 | assert(fld_idx > -1); |
| 1082 | |||
| 1083 | /* | ||
| 1084 | Don't allow the GC (or default expression) to refer itself or another GC | ||
| 1085 | (or default expressions) that is defined after it. | ||
| 1086 | */ | ||
| 1087 |
2/2✓ Branch 0 taken 83989 times.
✓ Branch 1 taken 1002 times.
|
84991 | if ((func_args->source != VGS_CHECK_CONSTRAINT) && |
| 1088 |
2/2✓ Branch 0 taken 789 times.
✓ Branch 1 taken 83200 times.
|
168980 | (field->is_gcol() || |
| 1089 |
4/4✓ Branch 0 taken 84991 times.
✓ Branch 1 taken 7334 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 92313 times.
|
261305 | field->has_insert_default_general_value_expression()) && |
| 1090 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1779 times.
|
1791 | field->field_index() >= fld_idx) { |
| 1091 | 24 | func_args->err_code = (func_args->source == VGS_GENERATED_COLUMN) | |
| 1092 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | ? ER_GENERATED_COLUMN_NON_PRIOR |
| 1093 | : ER_DEFAULT_VAL_GENERATED_NON_PRIOR; | ||
| 1094 | 12 | return true; | |
| 1095 | } | ||
| 1096 | /* | ||
| 1097 | If a generated column, default expression or check constraint depends | ||
| 1098 | on an auto_increment column: | ||
| 1099 | - calculation of the generated value is done before write_row(), | ||
| 1100 | - but the auto_increment value is determined in write_row() by the | ||
| 1101 | engine. | ||
| 1102 | So this case is forbidden. | ||
| 1103 | */ | ||
| 1104 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 92306 times.
|
92313 | if (field->is_flag_set(AUTO_INCREMENT_FLAG)) { |
| 1105 | 7 | func_args->err_code = | |
| 1106 | 7 | (func_args->source == VGS_GENERATED_COLUMN) | |
| 1107 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
13 | ? ER_GENERATED_COLUMN_REF_AUTO_INC |
| 1108 | 6 | : (func_args->source == VGS_DEFAULT_EXPRESSION) | |
| 1109 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | ? ER_DEFAULT_VAL_GENERATED_REF_AUTO_INC |
| 1110 | : ER_CHECK_CONSTRAINT_REFERS_AUTO_INCREMENT_COLUMN; | ||
| 1111 | 7 | return true; | |
| 1112 | } | ||
| 1113 | |||
| 1114 | 92306 | return false; | |
| 1115 | } | ||
| 1116 | |||
| 1117 | /** | ||
| 1118 | Check privileges of base table column | ||
| 1119 | */ | ||
| 1120 | |||
| 1121 | 53158099 | bool Item_field::check_column_privileges(uchar *arg) { | |
| 1122 | 53158099 | THD *thd = (THD *)arg; | |
| 1123 | |||
| 1124 | Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler( | ||
| 1125 |
1/2✓ Branch 0 taken 53158783 times.
✗ Branch 1 not taken.
|
53158099 | thd, context->view_error_handler, context->view_error_handler_arg); |
| 1126 |
3/4✓ Branch 0 taken 53161139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 53161088 times.
|
53158783 | if (check_column_grant_in_table_ref(thd, table_ref, field_name, |
| 1127 | strlen(field_name), | ||
| 1128 | thd->want_privilege)) { | ||
| 1129 | 51 | return true; | |
| 1130 | } | ||
| 1131 | |||
| 1132 | 53161088 | return false; | |
| 1133 | 53161139 | } | |
| 1134 | |||
| 1135 | /** | ||
| 1136 | Check privileges of view column. | ||
| 1137 | |||
| 1138 | @note this function will be called for columns from views and derived tables, | ||
| 1139 | however privilege check for derived tables should be skipped | ||
| 1140 | (those columns are checked against the base tables). | ||
| 1141 | */ | ||
| 1142 | |||
| 1143 | 4345655 | bool Item_view_ref::check_column_privileges(uchar *arg) { | |
| 1144 | 4345655 | THD *thd = (THD *)arg; | |
| 1145 | |||
| 1146 |
2/2✓ Branch 0 taken 267545 times.
✓ Branch 1 taken 4078110 times.
|
4345655 | if (cached_table->is_derived()) // Rely on checking underlying tables |
| 1147 | 267545 | return false; | |
| 1148 | |||
| 1149 | Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler( | ||
| 1150 |
1/2✓ Branch 0 taken 4078115 times.
✗ Branch 1 not taken.
|
4078110 | thd, context->view_error_handler, context->view_error_handler_arg); |
| 1151 | |||
| 1152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4078115 times.
|
4078115 | assert(strlen(cached_table->get_table_name()) > 0); |
| 1153 | |||
| 1154 |
3/4✓ Branch 0 taken 4078115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 4078095 times.
|
4078115 | if (check_column_grant_in_table_ref(thd, cached_table, field_name, |
| 1155 | strlen(field_name), thd->want_privilege)) | ||
| 1156 | 20 | return true; | |
| 1157 | |||
| 1158 | 4078095 | return false; | |
| 1159 | 4078115 | } | |
| 1160 | |||
| 1161 | 3896133 | bool Item::may_evaluate_const(const THD *thd) const { | |
| 1162 | // Ensure tables are locked whenever preparation is complete | ||
| 1163 |
3/4✓ Branch 0 taken 347911 times.
✓ Branch 1 taken 3548223 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 347911 times.
|
3896133 | assert(!thd->lex->is_exec_started() || thd->lex->is_query_tables_locked()); |
| 1164 |
2/2✓ Branch 0 taken 3851036 times.
✓ Branch 1 taken 45098 times.
|
7747171 | return !(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) && |
| 1165 |
2/2✓ Branch 0 taken 3464087 times.
✓ Branch 1 taken 386949 times.
|
3851036 | (const_item() || |
| 1166 |
4/4✓ Branch 0 taken 38249 times.
✓ Branch 1 taken 3425838 times.
✓ Branch 2 taken 16992 times.
✓ Branch 3 taken 21258 times.
|
7360222 | (const_for_execution() && thd->lex->is_exec_started())); |
| 1167 | } | ||
| 1168 | |||
| 1169 | 221119482 | bool Item::check_cols(uint c) { | |
| 1170 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 221119474 times.
|
221119482 | if (c != 1) { |
| 1171 | 8 | my_error(ER_OPERAND_COLUMNS, MYF(0), c); | |
| 1172 | 8 | return true; | |
| 1173 | } | ||
| 1174 | 221119474 | return false; | |
| 1175 | } | ||
| 1176 | |||
| 1177 | const Name_string null_name_string(nullptr, 0); | ||
| 1178 | |||
| 1179 | 77034607 | void Name_string::copy(const char *str, size_t length, const CHARSET_INFO *cs) { | |
| 1180 |
2/2✓ Branch 0 taken 2295801 times.
✓ Branch 1 taken 74738806 times.
|
77034607 | if (!length) { |
| 1181 | /* Empty string, used by AS or internal function like last_insert_id() */ | ||
| 1182 |
2/2✓ Branch 0 taken 2295780 times.
✓ Branch 1 taken 21 times.
|
2295801 | set(str ? "" : nullptr, 0); |
| 1183 | 2295805 | return; | |
| 1184 | } | ||
| 1185 |
2/2✓ Branch 0 taken 74737355 times.
✓ Branch 1 taken 1451 times.
|
74738806 | if (cs->ctype) { |
| 1186 | /* | ||
| 1187 | This will probably need a better implementation in the future: | ||
| 1188 | a function in CHARSET_INFO structure. | ||
| 1189 | */ | ||
| 1190 |
4/4✓ Branch 0 taken 75284788 times.
✓ Branch 1 taken 547406 times.
✓ Branch 2 taken 1094839 times.
✓ Branch 3 taken 74189949 times.
|
75832194 | while (length && !my_isgraph(cs, *str)) { // Fix problem with yacc |
| 1191 | 1094839 | length--; | |
| 1192 | 1094839 | str++; | |
| 1193 | } | ||
| 1194 | } | ||
| 1195 |
2/2✓ Branch 0 taken 41836899 times.
✓ Branch 1 taken 32901926 times.
|
74738806 | if (!my_charset_same(cs, system_charset_info)) { |
| 1196 | size_t res_length; | ||
| 1197 |
1/2✓ Branch 0 taken 41836905 times.
✗ Branch 1 not taken.
|
41836899 | char *tmp = sql_strmake_with_convert(str, length, cs, MAX_ALIAS_NAME, |
| 1198 | system_charset_info, &res_length); | ||
| 1199 |
2/2✓ Branch 0 taken 41836904 times.
✓ Branch 1 taken 1 times.
|
41836905 | set(tmp, tmp ? res_length : 0); |
| 1200 | } else { | ||
| 1201 | 32901926 | size_t len = min<size_t>(length, MAX_ALIAS_NAME); | |
| 1202 | 32901929 | char *tmp = sql_strmake(str, len); | |
| 1203 |
1/2✓ Branch 0 taken 32901926 times.
✗ Branch 1 not taken.
|
32901926 | set(tmp, tmp ? len : 0); |
| 1204 | } | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | 11781682 | void Item_name_string::copy(const char *str_arg, size_t length_arg, | |
| 1208 | const CHARSET_INFO *cs_arg, | ||
| 1209 | bool is_autogenerated_arg) { | ||
| 1210 | 11781682 | m_is_autogenerated = is_autogenerated_arg; | |
| 1211 | 11781682 | copy(str_arg, length_arg, cs_arg); | |
| 1212 |
5/6✓ Branch 0 taken 53 times.
✓ Branch 1 taken 11781630 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53 times.
✓ Branch 5 taken 11781630 times.
|
11781684 | if (length_arg > length() && !is_autogenerated()) { |
| 1213 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | ErrConvString tmp(str_arg, static_cast<uint>(length_arg), cs_arg); |
| 1214 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 27 times.
|
53 | if (length() == 0) |
| 1215 | 26 | push_warning_printf( | |
| 1216 |
2/4✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
26 | current_thd, Sql_condition::SL_WARNING, ER_NAME_BECOMES_EMPTY, |
| 1217 |
2/4✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
26 | ER_THD(current_thd, ER_NAME_BECOMES_EMPTY), tmp.ptr()); |
| 1218 | else | ||
| 1219 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
54 | push_warning_printf(current_thd, Sql_condition::SL_WARNING, |
| 1220 | ER_REMOVED_SPACES, | ||
| 1221 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
27 | ER_THD(current_thd, ER_REMOVED_SPACES), tmp.ptr()); |
| 1222 | } | ||
| 1223 | 11781683 | } | |
| 1224 | |||
| 1225 | /** | ||
| 1226 | @details | ||
| 1227 | This function is called when: | ||
| 1228 | - Comparing items in the WHERE clause (when doing where optimization) | ||
| 1229 | - When trying to find an ORDER BY/GROUP BY item in the SELECT part | ||
| 1230 | - When matching fields in multiple equality objects (Item_equal) | ||
| 1231 | */ | ||
| 1232 | |||
| 1233 | 129850 | bool Item::eq(const Item *item, bool) const { | |
| 1234 | /* | ||
| 1235 | Note, that this is never true if item is a Item_param: | ||
| 1236 | for all basic constants we have special checks, and Item_param's | ||
| 1237 | type() can be only among basic constant types. | ||
| 1238 | */ | ||
| 1239 |
4/4✓ Branch 0 taken 127593 times.
✓ Branch 1 taken 2257 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 127512 times.
|
129850 | return type() == item->type() && item_name.eq_safe(item->item_name); |
| 1240 | } | ||
| 1241 | |||
| 1242 | 64855 | Item *Item::safe_charset_converter(THD *thd, const CHARSET_INFO *tocs) { | |
| 1243 | Item_func_conv_charset *conv = | ||
| 1244 |
2/4✓ Branch 0 taken 64855 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64855 times.
✗ Branch 3 not taken.
|
64855 | new Item_func_conv_charset(thd, this, tocs, true); |
| 1245 |
3/4✓ Branch 0 taken 64855 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64741 times.
✓ Branch 3 taken 114 times.
|
64855 | return conv && conv->m_safe ? conv : nullptr; |
| 1246 | } | ||
| 1247 | |||
| 1248 | /** | ||
| 1249 | @details | ||
| 1250 | Created mostly for mysql_prepare_table(). Important | ||
| 1251 | when a string ENUM/SET column is described with a numeric default value: | ||
| 1252 | |||
| 1253 | CREATE TABLE t1(a SET('a') DEFAULT 1); | ||
| 1254 | |||
| 1255 | We cannot use generic Item::safe_charset_converter(), because | ||
| 1256 | the latter returns a non-fixed Item, so val_str() crashes afterwards. | ||
| 1257 | Override Item_num method, to return a fixed item. | ||
| 1258 | */ | ||
| 1259 | 107 | Item *Item_num::safe_charset_converter(THD *thd, const CHARSET_INFO *tocs) { | |
| 1260 | /* | ||
| 1261 | Item_num returns pure ASCII result, | ||
| 1262 | so conversion is needed only in case of "tricky" character | ||
| 1263 | sets like UCS2. If tocs is not "tricky", return the item itself. | ||
| 1264 | */ | ||
| 1265 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 92 times.
|
107 | if (!(tocs->state & MY_CS_NONASCII)) return this; |
| 1266 | |||
| 1267 | uint conv_errors; | ||
| 1268 | char buf[64], buf2[64]; | ||
| 1269 | 92 | String tmp(buf, sizeof(buf), &my_charset_bin); | |
| 1270 | 92 | String cstr(buf2, sizeof(buf2), &my_charset_bin); | |
| 1271 |
1/2✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
|
92 | String *ostr = val_str(&tmp); |
| 1272 |
1/2✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
|
92 | cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); |
| 1273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
|
92 | if (conv_errors > 0) { |
| 1274 | /* | ||
| 1275 | Safe conversion is not possible. | ||
| 1276 | We could not convert a string into the requested character set | ||
| 1277 | without data loss. The target charset does not cover all the | ||
| 1278 | characters from the string. Operation cannot be done correctly. | ||
| 1279 | */ | ||
| 1280 | ✗ | return nullptr; | |
| 1281 | } | ||
| 1282 | |||
| 1283 |
1/2✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
|
92 | char *ptr = thd->strmake(cstr.ptr(), cstr.length()); |
| 1284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
|
92 | if (ptr == nullptr) return nullptr; |
| 1285 | auto conv = | ||
| 1286 |
2/4✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
|
92 | new Item_string(ptr, cstr.length(), cstr.charset(), collation.derivation); |
| 1287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
|
92 | if (conv == nullptr) return nullptr; |
| 1288 | |||
| 1289 | /* Ensure that no one is going to change the result string */ | ||
| 1290 | 92 | conv->mark_result_as_const(); | |
| 1291 |
1/2✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
|
92 | conv->fix_char_length(max_char_length()); |
| 1292 | 92 | return conv; | |
| 1293 | 92 | } | |
| 1294 | |||
| 1295 | ✗ | Item *Item_func_pi::safe_charset_converter(THD *thd, const CHARSET_INFO *) { | |
| 1296 | char buf[64]; | ||
| 1297 | ✗ | String tmp(buf, sizeof(buf), &my_charset_bin); | |
| 1298 | ✗ | String *s = val_str(&tmp); | |
| 1299 | ✗ | char *ptr = thd->strmake(s->ptr(), s->length()); | |
| 1300 | ✗ | if (ptr == nullptr) return nullptr; | |
| 1301 | auto conv = | ||
| 1302 | ✗ | new Item_static_string_func(func_name, ptr, s->length(), s->charset()); | |
| 1303 | ✗ | if (conv == nullptr) return nullptr; | |
| 1304 | ✗ | conv->mark_result_as_const(); | |
| 1305 | ✗ | return conv; | |
| 1306 | } | ||
| 1307 | |||
| 1308 | 1836426 | Item *Item_string::safe_charset_converter(THD *thd, const CHARSET_INFO *tocs) { | |
| 1309 | 1836426 | return charset_converter(thd, tocs, true); | |
| 1310 | } | ||
| 1311 | |||
| 1312 | /** | ||
| 1313 | Convert a string item into the requested character set. | ||
| 1314 | |||
| 1315 | @param thd Thread handle. | ||
| 1316 | @param tocs Character set to to convert the string to. | ||
| 1317 | @param lossless Whether data loss is acceptable. | ||
| 1318 | |||
| 1319 | @return A new item representing the converted string. | ||
| 1320 | */ | ||
| 1321 | 1836764 | Item *Item_string::charset_converter(THD *thd, const CHARSET_INFO *tocs, | |
| 1322 | bool lossless) { | ||
| 1323 | uint conv_errors; | ||
| 1324 |
1/2✓ Branch 0 taken 1836764 times.
✗ Branch 1 not taken.
|
1836764 | String tmp, cstr, *ostr = val_str(&tmp); |
| 1325 |
1/2✓ Branch 0 taken 1836764 times.
✗ Branch 1 not taken.
|
1836764 | cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); |
| 1326 |
4/4✓ Branch 0 taken 1836426 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1836416 times.
|
1836764 | if (lossless && conv_errors > 0) { |
| 1327 | /* | ||
| 1328 | Safe conversion is not possible. | ||
| 1329 | We could not convert a string into the requested character set | ||
| 1330 | without data loss. The target charset does not cover all the | ||
| 1331 | characters from the string. Operation cannot be done correctly. | ||
| 1332 | */ | ||
| 1333 | 10 | return nullptr; | |
| 1334 | } | ||
| 1335 | |||
| 1336 |
1/2✓ Branch 0 taken 1836754 times.
✗ Branch 1 not taken.
|
1836754 | char *ptr = thd->strmake(cstr.ptr(), cstr.length()); |
| 1337 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1836754 times.
|
1836754 | if (ptr == nullptr) return nullptr; |
| 1338 | auto conv = | ||
| 1339 |
2/4✓ Branch 0 taken 1836754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1836754 times.
✗ Branch 3 not taken.
|
1836754 | new Item_string(ptr, cstr.length(), cstr.charset(), collation.derivation); |
| 1340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1836754 times.
|
1836754 | if (conv == nullptr) return nullptr; |
| 1341 | /* Ensure that no one is going to change the result string */ | ||
| 1342 | 1836754 | conv->mark_result_as_const(); | |
| 1343 | 1836754 | return conv; | |
| 1344 | 1836764 | } | |
| 1345 | |||
| 1346 | ✗ | Item *Item_param::safe_charset_converter(THD *thd, const CHARSET_INFO *tocs) { | |
| 1347 | ✗ | if (may_evaluate_const(thd)) { | |
| 1348 | ✗ | String tmp, cstr, *ostr = val_str(&tmp); | |
| 1349 | |||
| 1350 | ✗ | if (null_value) { | |
| 1351 | ✗ | auto cnvitem = new Item_null(); | |
| 1352 | ✗ | if (cnvitem == nullptr) return nullptr; | |
| 1353 | ✗ | cnvitem->collation.set(tocs); | |
| 1354 | ✗ | return cnvitem; | |
| 1355 | } else { | ||
| 1356 | uint conv_errors; | ||
| 1357 | ✗ | cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, | |
| 1358 | &conv_errors); | ||
| 1359 | |||
| 1360 | ✗ | if (conv_errors > 0) return nullptr; | |
| 1361 | |||
| 1362 | ✗ | char *ptr = thd->strmake(cstr.ptr(), cstr.length()); | |
| 1363 | ✗ | if (ptr == nullptr) return nullptr; | |
| 1364 | ✗ | auto cnvitem = new Item_string(ptr, cstr.length(), cstr.charset(), | |
| 1365 | ✗ | collation.derivation); | |
| 1366 | ✗ | if (cnvitem == nullptr) return nullptr; | |
| 1367 | ✗ | cnvitem->mark_result_as_const(); | |
| 1368 | ✗ | return cnvitem; | |
| 1369 | } | ||
| 1370 | } | ||
| 1371 | ✗ | return Item::safe_charset_converter(thd, tocs); | |
| 1372 | } | ||
| 1373 | |||
| 1374 | 3 | Item *Item_static_string_func::safe_charset_converter( | |
| 1375 | THD *thd, const CHARSET_INFO *tocs) { | ||
| 1376 | uint conv_errors; | ||
| 1377 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | String tmp, cstr, *ostr = val_str(&tmp); |
| 1378 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); |
| 1379 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (conv_errors > 0) { |
| 1380 | /* | ||
| 1381 | Safe conversion is not possible. | ||
| 1382 | We could not convert a string into the requested character set | ||
| 1383 | without data loss. The target charset does not cover all the | ||
| 1384 | characters from the string. Operation cannot be done correctly. | ||
| 1385 | */ | ||
| 1386 | ✗ | return nullptr; | |
| 1387 | } | ||
| 1388 | |||
| 1389 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | char *ptr = thd->strmake(cstr.ptr(), cstr.length()); |
| 1390 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ptr == nullptr) return nullptr; |
| 1391 | 3 | auto conv = new Item_static_string_func(func_name, ptr, cstr.length(), | |
| 1392 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | cstr.charset(), collation.derivation); |
| 1393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (conv == nullptr) return nullptr; |
| 1394 | /* Ensure that no one is going to change the result string */ | ||
| 1395 | 3 | conv->mark_result_as_const(); | |
| 1396 | 3 | return conv; | |
| 1397 | 3 | } | |
| 1398 | |||
| 1399 | 1021453 | bool Item_string::eq(const Item *item, bool binary_cmp) const { | |
| 1400 |
6/6✓ Branch 0 taken 503413 times.
✓ Branch 1 taken 518052 times.
✓ Branch 2 taken 503401 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 503403 times.
✓ Branch 5 taken 518058 times.
|
1021453 | if (type() == item->type() && item->basic_const_item()) { |
| 1401 | // Should be OK for a basic constant. | ||
| 1402 | 503403 | Item *arg = const_cast<Item *>(item); | |
| 1403 | 503403 | String str; | |
| 1404 |
4/6✓ Branch 0 taken 447839 times.
✓ Branch 1 taken 55564 times.
✓ Branch 2 taken 447842 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 447842 times.
✗ Branch 5 not taken.
|
503403 | if (binary_cmp) return !stringcmp(&str_value, arg->val_str(&str)); |
| 1405 |
2/2✓ Branch 0 taken 33048 times.
✓ Branch 1 taken 22516 times.
|
88612 | return (collation.collation == arg->collation.collation && |
| 1406 |
4/6✓ Branch 0 taken 33048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33048 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32370 times.
✓ Branch 5 taken 678 times.
|
88612 | !sortcmp(&str_value, arg->val_str(&str), collation.collation)); |
| 1407 | 503406 | } | |
| 1408 | 518058 | return false; | |
| 1409 | } | ||
| 1410 | |||
| 1411 | 9341 | bool Item::get_date_from_string(MYSQL_TIME *ltime, my_time_flags_t flags) { | |
| 1412 | char buff[MAX_DATE_STRING_REP_LENGTH]; | ||
| 1413 | 9341 | String tmp(buff, sizeof(buff), &my_charset_bin), *res; | |
| 1414 |
3/4✓ Branch 0 taken 9341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 9304 times.
|
9341 | if (!(res = val_str(&tmp))) { |
| 1415 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); |
| 1416 | 37 | return true; | |
| 1417 | } | ||
| 1418 |
1/2✓ Branch 0 taken 9304 times.
✗ Branch 1 not taken.
|
9304 | return str_to_datetime_with_warn(res, ltime, flags); |
| 1419 | 9341 | } | |
| 1420 | |||
| 1421 | 8 | bool Item::get_date_from_real(MYSQL_TIME *ltime, my_time_flags_t flags) { | |
| 1422 | 8 | double value = val_real(); | |
| 1423 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (null_value) { |
| 1424 | 1 | set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); | |
| 1425 | 1 | return true; | |
| 1426 | } | ||
| 1427 | 7 | return my_double_to_datetime_with_warn(value, ltime, flags); | |
| 1428 | } | ||
| 1429 | |||
| 1430 | 58 | bool Item::get_date_from_decimal(MYSQL_TIME *ltime, my_time_flags_t flags) { | |
| 1431 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | my_decimal buf, *decimal = val_decimal(&buf); |
| 1432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (null_value) { |
| 1433 | ✗ | set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); | |
| 1434 | ✗ | return true; | |
| 1435 | } | ||
| 1436 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | return my_decimal_to_datetime_with_warn(decimal, ltime, flags); |
| 1437 | 58 | } | |
| 1438 | |||
| 1439 | 1073 | bool Item::get_date_from_int(MYSQL_TIME *ltime, my_time_flags_t flags) { | |
| 1440 | 1073 | longlong value = val_int(); | |
| 1441 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1071 times.
|
1073 | if (null_value) { |
| 1442 | 2 | set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); | |
| 1443 | 2 | return true; | |
| 1444 | } | ||
| 1445 | 1071 | return my_longlong_to_datetime_with_warn(value, ltime, flags); | |
| 1446 | } | ||
| 1447 | |||
| 1448 | 162 | bool Item::get_date_from_time(MYSQL_TIME *ltime) { | |
| 1449 | MYSQL_TIME tm; | ||
| 1450 |
3/4✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 151 times.
|
162 | if (get_time(&tm)) { |
| 1451 |
5/8✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
11 | assert(null_value || current_thd->is_error()); |
| 1452 | 11 | return true; | |
| 1453 | } | ||
| 1454 |
2/4✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 151 times.
✗ Branch 3 not taken.
|
151 | time_to_datetime(current_thd, &tm, ltime); |
| 1455 | 151 | return false; | |
| 1456 | } | ||
| 1457 | |||
| 1458 | 3 | bool Item::get_date_from_numeric(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) { | |
| 1459 |
3/5✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
3 | switch (result_type()) { |
| 1460 | 1 | case REAL_RESULT: | |
| 1461 | 1 | return get_date_from_real(ltime, fuzzydate); | |
| 1462 | 1 | case DECIMAL_RESULT: | |
| 1463 | 1 | return get_date_from_decimal(ltime, fuzzydate); | |
| 1464 | 1 | case INT_RESULT: | |
| 1465 | 1 | return get_date_from_int(ltime, fuzzydate); | |
| 1466 | ✗ | case STRING_RESULT: | |
| 1467 | case ROW_RESULT: | ||
| 1468 | case INVALID_RESULT: | ||
| 1469 | ✗ | assert(0); | |
| 1470 | } | ||
| 1471 | ✗ | return (null_value = true); // Impossible result_type | |
| 1472 | } | ||
| 1473 | |||
| 1474 | /** | ||
| 1475 | Get the value of the function as a MYSQL_TIME structure. | ||
| 1476 | As a extra convenience the time structure is reset on error! | ||
| 1477 | */ | ||
| 1478 | |||
| 1479 | 269 | bool Item::get_date_from_non_temporal(MYSQL_TIME *ltime, | |
| 1480 | my_time_flags_t fuzzydate) { | ||
| 1481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
|
269 | assert(!is_temporal()); |
| 1482 |
4/6✓ Branch 0 taken 231 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
269 | switch (result_type()) { |
| 1483 | 231 | case STRING_RESULT: | |
| 1484 | 231 | return get_date_from_string(ltime, fuzzydate); | |
| 1485 | 1 | case REAL_RESULT: | |
| 1486 | 1 | return get_date_from_real(ltime, fuzzydate); | |
| 1487 | 20 | case DECIMAL_RESULT: | |
| 1488 | 20 | return get_date_from_decimal(ltime, fuzzydate); | |
| 1489 | 17 | case INT_RESULT: | |
| 1490 | 17 | return get_date_from_int(ltime, fuzzydate); | |
| 1491 | ✗ | case ROW_RESULT: | |
| 1492 | case INVALID_RESULT: | ||
| 1493 | ✗ | assert(0); | |
| 1494 | } | ||
| 1495 | ✗ | return (null_value = true); // Impossible result_type | |
| 1496 | } | ||
| 1497 | |||
| 1498 | 2378 | bool Item::get_time_from_string(MYSQL_TIME *ltime) { | |
| 1499 | char buff[MAX_DATE_STRING_REP_LENGTH]; | ||
| 1500 | 2378 | String tmp(buff, sizeof(buff), &my_charset_bin), *res; | |
| 1501 |
3/4✓ Branch 0 taken 2378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 2368 times.
|
2378 | if (!(res = val_str(&tmp))) { |
| 1502 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); |
| 1503 | 10 | return true; | |
| 1504 | } | ||
| 1505 |
1/2✓ Branch 0 taken 2368 times.
✗ Branch 1 not taken.
|
2368 | return str_to_time_with_warn(res, ltime); |
| 1506 | 2378 | } | |
| 1507 | |||
| 1508 | 18 | bool Item::get_time_from_real(MYSQL_TIME *ltime) { | |
| 1509 | 18 | double value = val_real(); | |
| 1510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (null_value) { |
| 1511 | ✗ | set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); | |
| 1512 | ✗ | return true; | |
| 1513 | } | ||
| 1514 | 18 | return my_double_to_time_with_warn(value, ltime); | |
| 1515 | } | ||
| 1516 | |||
| 1517 | 79 | bool Item::get_time_from_decimal(MYSQL_TIME *ltime) { | |
| 1518 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | my_decimal buf, *decimal = val_decimal(&buf); |
| 1519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | if (null_value) { |
| 1520 | ✗ | set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); | |
| 1521 | ✗ | return true; | |
| 1522 | } | ||
| 1523 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | return my_decimal_to_time_with_warn(decimal, ltime); |
| 1524 | 79 | } | |
| 1525 | |||
| 1526 | 1179 | bool Item::get_time_from_int(MYSQL_TIME *ltime) { | |
| 1527 | 1179 | longlong value = val_int(); | |
| 1528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1179 times.
|
1179 | if (null_value) { |
| 1529 | ✗ | set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); | |
| 1530 | ✗ | return true; | |
| 1531 | } | ||
| 1532 | 1179 | return my_longlong_to_time_with_warn(value, ltime); | |
| 1533 | } | ||
| 1534 | |||
| 1535 | 11 | bool Item::get_time_from_date(MYSQL_TIME *ltime) { | |
| 1536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | assert(fixed == 1); |
| 1537 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
|
11 | if (get_date(ltime, TIME_FUZZY_DATE)) // Need this check if NULL value |
| 1538 | 4 | return true; | |
| 1539 | 7 | set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); | |
| 1540 | 7 | return false; | |
| 1541 | } | ||
| 1542 | |||
| 1543 | 53 | bool Item::get_time_from_datetime(MYSQL_TIME *ltime) { | |
| 1544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | assert(fixed == 1); |
| 1545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | if (get_date(ltime, TIME_FUZZY_DATE)) return true; |
| 1546 | 53 | datetime_to_time(ltime); | |
| 1547 | 53 | return false; | |
| 1548 | } | ||
| 1549 | |||
| 1550 | 4 | bool Item::get_time_from_numeric(MYSQL_TIME *ltime) { | |
| 1551 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(!is_temporal()); |
| 1552 |
3/5✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
4 | switch (result_type()) { |
| 1553 | 1 | case REAL_RESULT: | |
| 1554 | 1 | return get_time_from_real(ltime); | |
| 1555 | 1 | case DECIMAL_RESULT: | |
| 1556 | 1 | return get_time_from_decimal(ltime); | |
| 1557 | 2 | case INT_RESULT: | |
| 1558 | 2 | return get_time_from_int(ltime); | |
| 1559 | ✗ | case STRING_RESULT: | |
| 1560 | case ROW_RESULT: | ||
| 1561 | case INVALID_RESULT: | ||
| 1562 | ✗ | assert(0); | |
| 1563 | } | ||
| 1564 | ✗ | return (null_value = true); // Impossible result type | |
| 1565 | } | ||
| 1566 | |||
| 1567 | /** | ||
| 1568 | Get time value from int, real, decimal or string. | ||
| 1569 | |||
| 1570 | As a extra convenience the time structure is reset on error! | ||
| 1571 | */ | ||
| 1572 | |||
| 1573 | 77 | bool Item::get_time_from_non_temporal(MYSQL_TIME *ltime) { | |
| 1574 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | assert(!is_temporal()); |
| 1575 |
3/6✓ Branch 0 taken 72 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
77 | switch (result_type()) { |
| 1576 | 72 | case STRING_RESULT: | |
| 1577 | 72 | return get_time_from_string(ltime); | |
| 1578 | 3 | case REAL_RESULT: | |
| 1579 | 3 | return get_time_from_real(ltime); | |
| 1580 | ✗ | case DECIMAL_RESULT: | |
| 1581 | ✗ | return get_time_from_decimal(ltime); | |
| 1582 | 2 | case INT_RESULT: | |
| 1583 | 2 | return get_time_from_int(ltime); | |
| 1584 | ✗ | case ROW_RESULT: | |
| 1585 | case INVALID_RESULT: | ||
| 1586 | ✗ | assert(0); | |
| 1587 | } | ||
| 1588 | ✗ | return (null_value = true); // Impossible result type | |
| 1589 | } | ||
| 1590 | |||
| 1591 | /** | ||
| 1592 | If argument is NULL, sets null_value. Otherwise: | ||
| 1593 | if invalid DATETIME value, or a valid DATETIME value but which is out of | ||
| 1594 | the supported Unix timestamp range, sets 'tm' to 0. | ||
| 1595 | */ | ||
| 1596 | 426 | bool Item::get_timeval(my_timeval *tm, int *warnings) { | |
| 1597 | MYSQL_TIME ltime; | ||
| 1598 |
3/4✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 413 times.
|
426 | if (get_date(<ime, TIME_FUZZY_DATE)) { |
| 1599 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
|
13 | if (null_value) return true; /* Value is NULL */ |
| 1600 | 4 | goto zero; /* Could not extract date from the value */ | |
| 1601 | } | ||
| 1602 |
4/6✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 413 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 389 times.
|
413 | if (datetime_to_timeval(<ime, *current_thd->time_zone(), tm, warnings)) |
| 1603 | 24 | goto zero; /* Value is out of the supported range */ | |
| 1604 | 389 | return false; /* Value is a good Unix timestamp */ | |
| 1605 | 28 | zero: | |
| 1606 | 28 | tm->m_tv_sec = tm->m_tv_usec = 0; | |
| 1607 | 28 | return false; | |
| 1608 | } | ||
| 1609 | |||
| 1610 | 6584027 | const CHARSET_INFO *Item::default_charset() { | |
| 1611 | 6584027 | return current_thd->variables.collation_connection; | |
| 1612 | } | ||
| 1613 | |||
| 1614 | /* | ||
| 1615 | Save value in field, but don't give any warnings | ||
| 1616 | |||
| 1617 | NOTES | ||
| 1618 | This is used to temporary store and retrieve a value in a column, | ||
| 1619 | for example in opt_range to adjust the key value to fit the column. | ||
| 1620 | */ | ||
| 1621 | |||
| 1622 | 12475807 | type_conversion_status Item::save_in_field_no_warnings(Field *field, | |
| 1623 | bool no_conversions) { | ||
| 1624 |
1/2✓ Branch 0 taken 12475887 times.
✗ Branch 1 not taken.
|
12475807 | DBUG_TRACE; |
| 1625 | 12475887 | TABLE *table = field->table; | |
| 1626 |
1/2✓ Branch 0 taken 12475888 times.
✗ Branch 1 not taken.
|
12475887 | THD *thd = current_thd; |
| 1627 | 12475888 | enum_check_fields tmp = thd->check_for_truncated_fields; | |
| 1628 | 12475888 | my_bitmap_map *old_map = dbug_tmp_use_all_columns(table, table->write_set); | |
| 1629 | 12475860 | sql_mode_t sql_mode = thd->variables.sql_mode; | |
| 1630 | /* | ||
| 1631 | For cases like data truncation still warning is reported here. Which was | ||
| 1632 | avoided before with THD::abort_on_warning flag. Since the flag is removed | ||
| 1633 | now, until MODE_NO_ZERO_IN_DATE, MODE_NO_ZERO_DATE and | ||
| 1634 | MODE_ERROR_FOR_DIVISION_BY_ZERO are merged with strict mode, removing even | ||
| 1635 | strict modes from sql_mode here to avoid warnings. | ||
| 1636 | */ | ||
| 1637 | 12475860 | thd->variables.sql_mode &= | |
| 1638 | ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_STRICT_ALL_TABLES | | ||
| 1639 | MODE_STRICT_TRANS_TABLES); | ||
| 1640 | 12475860 | thd->check_for_truncated_fields = CHECK_FIELD_IGNORE; | |
| 1641 | |||
| 1642 |
1/2✓ Branch 0 taken 12475908 times.
✗ Branch 1 not taken.
|
12475860 | const type_conversion_status res = save_in_field(field, no_conversions); |
| 1643 | |||
| 1644 | 12475908 | thd->check_for_truncated_fields = tmp; | |
| 1645 | 12475908 | dbug_tmp_restore_column_map(table->write_set, old_map); | |
| 1646 | 12475895 | thd->variables.sql_mode = sql_mode; | |
| 1647 | 12475908 | return res; | |
| 1648 | 12475895 | } | |
| 1649 | |||
| 1650 | 3372 | bool Item::is_blob_field() const { | |
| 1651 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3372 times.
|
3372 | assert(fixed); |
| 1652 | |||
| 1653 | 3372 | enum_field_types type = data_type(); | |
| 1654 |
4/4✓ Branch 0 taken 3361 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 3358 times.
✓ Branch 3 taken 3 times.
|
6730 | return (type == MYSQL_TYPE_BLOB || type == MYSQL_TYPE_GEOMETRY || |
| 1655 | // Char length, not the byte one, should be taken into account | ||
| 1656 |
2/2✓ Branch 0 taken 94 times.
✓ Branch 1 taken 3264 times.
|
3358 | max_length / collation.collation->mbmaxlen > |
| 1657 | 3372 | CONVERT_IF_BIGGER_TO_BLOB); | |
| 1658 | } | ||
| 1659 | |||
| 1660 | /***************************************************************************** | ||
| 1661 | Item_sp_variable methods | ||
| 1662 | *****************************************************************************/ | ||
| 1663 | |||
| 1664 | 823163 | Item_sp_variable::Item_sp_variable(const Name_string sp_var_name) | |
| 1665 | 823163 | : m_name(sp_var_name) {} | |
| 1666 | |||
| 1667 | 98526 | bool Item_sp_variable::fix_fields(THD *, Item **) { | |
| 1668 | 98526 | Item *it = this_item(); | |
| 1669 | |||
| 1670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98527 times.
|
98527 | assert(it->fixed); |
| 1671 | |||
| 1672 | 98527 | max_length = it->max_length; | |
| 1673 | 98527 | decimals = it->decimals; | |
| 1674 | 98527 | unsigned_flag = it->unsigned_flag; | |
| 1675 | 98527 | collation.set(it->collation); | |
| 1676 | 98527 | set_data_type(it->data_type()); | |
| 1677 | |||
| 1678 | 98526 | fixed = true; | |
| 1679 | |||
| 1680 | 98526 | return false; | |
| 1681 | } | ||
| 1682 | |||
| 1683 | 372601 | double Item_sp_variable::val_real() { | |
| 1684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372601 times.
|
372601 | assert(fixed); |
| 1685 | 372601 | Item *it = this_item(); | |
| 1686 | 372604 | double ret = it->val_real(); | |
| 1687 | 372604 | null_value = it->null_value; | |
| 1688 | 372604 | return ret; | |
| 1689 | } | ||
| 1690 | |||
| 1691 | 10725332 | longlong Item_sp_variable::val_int() { | |
| 1692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10725332 times.
|
10725332 | assert(fixed); |
| 1693 | 10725332 | Item *it = this_item(); | |
| 1694 | 10725997 | longlong ret = it->val_int(); | |
| 1695 | 10725951 | null_value = it->null_value; | |
| 1696 | 10725951 | return ret; | |
| 1697 | } | ||
| 1698 | |||
| 1699 | 1905272 | String *Item_sp_variable::val_str(String *sp) { | |
| 1700 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905272 times.
|
1905272 | assert(fixed); |
| 1701 | 1905272 | Item *it = this_item(); | |
| 1702 | 1905477 | String *res = it->val_str(sp); | |
| 1703 | |||
| 1704 | 1905443 | null_value = it->null_value; | |
| 1705 | |||
| 1706 |
2/2✓ Branch 0 taken 214 times.
✓ Branch 1 taken 1905229 times.
|
1905443 | if (!res) return nullptr; |
| 1707 | |||
| 1708 | /* | ||
| 1709 | This way we mark returned value of val_str as const, | ||
| 1710 | so that various functions (e.g. CONCAT) won't try to | ||
| 1711 | modify the value of the Item. Analogous mechanism is | ||
| 1712 | implemented for Item_param. | ||
| 1713 | Without this trick Item_splocal could be changed as a | ||
| 1714 | side-effect of expression computation. Here is an example | ||
| 1715 | of what happens without it: suppose x is varchar local | ||
| 1716 | variable in a SP with initial value 'ab' Then | ||
| 1717 | select concat(x,'c'); | ||
| 1718 | would change x's value to 'abc', as Item_func_concat::val_str() | ||
| 1719 | would use x's internal buffer to compute the result. | ||
| 1720 | This is intended behaviour of Item_func_concat. Comments to | ||
| 1721 | Item_param class contain some more details on the topic. | ||
| 1722 | */ | ||
| 1723 | |||
| 1724 |
1/2✓ Branch 0 taken 1905229 times.
✗ Branch 1 not taken.
|
1905229 | if (res != &str_value) |
| 1725 | 1905229 | str_value.set(res->ptr(), res->length(), res->charset()); | |
| 1726 | else | ||
| 1727 | ✗ | res->mark_as_const(); | |
| 1728 | |||
| 1729 | 1905251 | return &str_value; | |
| 1730 | } | ||
| 1731 | |||
| 1732 | 423788 | my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value) { | |
| 1733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 423788 times.
|
423788 | assert(fixed); |
| 1734 | 423788 | Item *it = this_item(); | |
| 1735 | 423788 | my_decimal *val = it->val_decimal(decimal_value); | |
| 1736 | 423788 | null_value = it->null_value; | |
| 1737 | 423788 | return val; | |
| 1738 | } | ||
| 1739 | |||
| 1740 | ✗ | bool Item_sp_variable::val_json(Json_wrapper *wr) { | |
| 1741 | ✗ | assert(fixed); | |
| 1742 | ✗ | Item *it = this_item(); | |
| 1743 | ✗ | bool result = it->val_json(wr); | |
| 1744 | ✗ | null_value = it->null_value; | |
| 1745 | ✗ | return result; | |
| 1746 | } | ||
| 1747 | |||
| 1748 | 27 | bool Item_sp_variable::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) { | |
| 1749 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | assert(fixed); |
| 1750 | 27 | Item *it = this_item(); | |
| 1751 | 27 | return (null_value = it->get_date(ltime, fuzzydate)); | |
| 1752 | } | ||
| 1753 | |||
| 1754 | 5 | bool Item_sp_variable::get_time(MYSQL_TIME *ltime) { | |
| 1755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | assert(fixed); |
| 1756 | 5 | Item *it = this_item(); | |
| 1757 | 5 | return (null_value = it->get_time(ltime)); | |
| 1758 | } | ||
| 1759 | |||
| 1760 | 706065 | bool Item_sp_variable::is_null() { return this_item()->is_null(); } | |
| 1761 | |||
| 1762 | /***************************************************************************** | ||
| 1763 | Item_splocal methods | ||
| 1764 | *****************************************************************************/ | ||
| 1765 | |||
| 1766 | 801119 | Item_splocal::Item_splocal(const Name_string sp_var_name, uint sp_var_idx, | |
| 1767 | enum_field_types sp_var_type, uint pos_in_q, | ||
| 1768 | 801119 | uint len_in_q) | |
| 1769 | : Item_sp_variable(sp_var_name), | ||
| 1770 | 801122 | m_var_idx(sp_var_idx), | |
| 1771 | 801122 | limit_clause_param(false), | |
| 1772 | 801122 | pos_in_query(pos_in_q), | |
| 1773 | 801119 | len_in_query(len_in_q) { | |
| 1774 | 801122 | set_nullable(true); | |
| 1775 | |||
| 1776 | 801122 | sp_var_type = real_type_to_type(sp_var_type); | |
| 1777 |
1/2✓ Branch 0 taken 801121 times.
✗ Branch 1 not taken.
|
801121 | m_type = sp_map_item_type(sp_var_type); |
| 1778 | 801121 | set_data_type(sp_var_type); | |
| 1779 |
1/2✓ Branch 0 taken 801121 times.
✗ Branch 1 not taken.
|
801123 | m_result_type = sp_map_result_type(sp_var_type); |
| 1780 | 801121 | } | |
| 1781 | |||
| 1782 | 20505928 | Item *Item_splocal::this_item() { | |
| 1783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20506695 times.
|
20505928 | assert(m_sp == current_thd->sp_runtime_ctx->sp); |
| 1784 | |||
| 1785 | 20506695 | return current_thd->sp_runtime_ctx->get_item(m_var_idx); | |
| 1786 | } | ||
| 1787 | |||
| 1788 | ✗ | const Item *Item_splocal::this_item() const { | |
| 1789 | ✗ | assert(m_sp == current_thd->sp_runtime_ctx->sp); | |
| 1790 | |||
| 1791 | ✗ | return current_thd->sp_runtime_ctx->get_item(m_var_idx); | |
| 1792 | } | ||
| 1793 | |||
| 1794 | 139980 | Item **Item_splocal::this_item_addr(THD *thd, Item **) { | |
| 1795 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 139980 times.
|
139980 | assert(m_sp == thd->sp_runtime_ctx->sp); |
| 1796 | |||
| 1797 | 139980 | return thd->sp_runtime_ctx->get_item_addr(m_var_idx); | |
| 1798 | } | ||
| 1799 | |||
| 1800 | 106 | bool Item_splocal::val_json(Json_wrapper *result) { | |
| 1801 | 106 | Item *it = this_item(); | |
| 1802 | 106 | bool ret = it->val_json(result); | |
| 1803 | 106 | null_value = it->null_value; | |
| 1804 | 106 | return ret; | |
| 1805 | } | ||
| 1806 | |||
| 1807 | 7345 | void Item_splocal::print(const THD *thd, String *str, enum_query_type) const { | |
| 1808 | // While reparsing a derived table condition, print the SP variable name. | ||
| 1809 | // Otherwise, print the SP variable name, followed by '@' and the variable | ||
| 1810 | // index. | ||
| 1811 | 7345 | str->reserve(m_name.length() + 8); | |
| 1812 | 7345 | str->append(m_name); | |
| 1813 |
2/2✓ Branch 0 taken 7335 times.
✓ Branch 1 taken 10 times.
|
7345 | if (!thd->lex->reparse_derived_table_condition) { |
| 1814 | 7335 | str->append('@'); | |
| 1815 | 7335 | qs_append(m_var_idx, str); | |
| 1816 | } | ||
| 1817 | 7345 | } | |
| 1818 | |||
| 1819 | 755 | bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it) { | |
| 1820 | 755 | return ctx->set_variable(thd, get_var_idx(), it); | |
| 1821 | } | ||
| 1822 | |||
| 1823 | /***************************************************************************** | ||
| 1824 | Item_case_expr methods | ||
| 1825 | *****************************************************************************/ | ||
| 1826 | |||
| 1827 | 22043 | Item_case_expr::Item_case_expr(uint case_expr_id) | |
| 1828 | : Item_sp_variable(Name_string(STRING_WITH_LEN("case_expr"))), | ||
| 1829 |
1/2✓ Branch 0 taken 22043 times.
✗ Branch 1 not taken.
|
22043 | m_case_expr_id(case_expr_id) {} |
| 1830 | |||
| 1831 | 156917 | Item *Item_case_expr::this_item() { | |
| 1832 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 156917 times.
|
156917 | assert(m_sp == current_thd->sp_runtime_ctx->sp); |
| 1833 | |||
| 1834 | 156917 | return current_thd->sp_runtime_ctx->get_case_expr(m_case_expr_id); | |
| 1835 | } | ||
| 1836 | |||
| 1837 | 87954 | const Item *Item_case_expr::this_item() const { | |
| 1838 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 87954 times.
|
87954 | assert(m_sp == current_thd->sp_runtime_ctx->sp); |
| 1839 | |||
| 1840 | 87954 | return current_thd->sp_runtime_ctx->get_case_expr(m_case_expr_id); | |
| 1841 | } | ||
| 1842 | |||
| 1843 | ✗ | Item **Item_case_expr::this_item_addr(THD *thd, Item **) { | |
| 1844 | ✗ | assert(m_sp == thd->sp_runtime_ctx->sp); | |
| 1845 | |||
| 1846 | ✗ | return thd->sp_runtime_ctx->get_case_expr_addr(m_case_expr_id); | |
| 1847 | } | ||
| 1848 | |||
| 1849 | 27 | void Item_case_expr::print(const THD *, String *str, enum_query_type) const { | |
| 1850 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (str->reserve(MAX_INT_WIDTH + sizeof("case_expr@"))) |
| 1851 | ✗ | return; /* purecov: inspected */ | |
| 1852 | 27 | (void)str->append(STRING_WITH_LEN("case_expr@")); | |
| 1853 | 27 | qs_append(m_case_expr_id, str); | |
| 1854 | } | ||
| 1855 | |||
| 1856 | /***************************************************************************** | ||
| 1857 | Item_name_const methods | ||
| 1858 | *****************************************************************************/ | ||
| 1859 | |||
| 1860 | 8 | double Item_name_const::val_real() { | |
| 1861 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | assert(fixed); |
| 1862 | 8 | double ret = value_item->val_real(); | |
| 1863 | 8 | null_value = value_item->null_value; | |
| 1864 | 8 | return ret; | |
| 1865 | } | ||
| 1866 | |||
| 1867 | 736 | longlong Item_name_const::val_int() { | |
| 1868 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 736 times.
|
736 | assert(fixed); |
| 1869 | 736 | longlong ret = value_item->val_int(); | |
| 1870 | 736 | null_value = value_item->null_value; | |
| 1871 | 736 | return ret; | |
| 1872 | } | ||
| 1873 | |||
| 1874 | 15 | String *Item_name_const::val_str(String *sp) { | |
| 1875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(fixed); |
| 1876 | 15 | String *ret = value_item->val_str(sp); | |
| 1877 | 15 | null_value = value_item->null_value; | |
| 1878 | 15 | return ret; | |
| 1879 | } | ||
| 1880 | |||
| 1881 | 2 | my_decimal *Item_name_const::val_decimal(my_decimal *decimal_value) { | |
| 1882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(fixed); |
| 1883 | 2 | my_decimal *val = value_item->val_decimal(decimal_value); | |
| 1884 | 2 | null_value = value_item->null_value; | |
| 1885 | 2 | return val; | |
| 1886 | } | ||
| 1887 | |||
| 1888 | 1 | bool Item_name_const::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) { | |
| 1889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | assert(fixed); |
| 1890 | 1 | return (null_value = value_item->get_date(ltime, fuzzydate)); | |
| 1891 | } | ||
| 1892 | |||
| 1893 | 1 | bool Item_name_const::get_time(MYSQL_TIME *ltime) { | |
| 1894 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | assert(fixed); |
| 1895 | 1 | return (null_value = value_item->get_time(ltime)); | |
| 1896 | } | ||
| 1897 | |||
| 1898 | 41 | bool Item_name_const::is_null() { return value_item->is_null(); } | |
| 1899 | |||
| 1900 | 8686 | Item_name_const::Item_name_const(const POS &pos, Item *name_arg, Item *val) | |
| 1901 | 8686 | : super(pos), value_item(val), name_item(name_arg) { | |
| 1902 | 8686 | set_nullable(true); | |
| 1903 | 8686 | } | |
| 1904 | |||
| 1905 | 8686 | bool Item_name_const::itemize(Parse_context *pc, Item **res) { | |
| 1906 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8686 times.
|
8686 | if (skip_itemize(res)) return false; |
| 1907 |
3/6✓ Branch 0 taken 8686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8686 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8686 times.
|
17372 | if (super::itemize(pc, res) || value_item->itemize(pc, &value_item) || |
| 1908 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8686 times.
|
8686 | name_item->itemize(pc, &name_item)) |
| 1909 | ✗ | return true; | |
| 1910 | /* | ||
| 1911 | The name and value argument to NAME_CONST can only be a literal constant. | ||
| 1912 | This (internal, although documented) feature is only supported for the | ||
| 1913 | stored procedure binlog's needs, cf. subst_spvars(). | ||
| 1914 | |||
| 1915 | Apart from plain literals, some extra logic are needed to support a | ||
| 1916 | collation specifier and to handle negative constant values. | ||
| 1917 | */ | ||
| 1918 | 8686 | valid_args = false; | |
| 1919 | |||
| 1920 |
2/2✓ Branch 0 taken 8683 times.
✓ Branch 1 taken 3 times.
|
8686 | if (name_item->basic_const_item()) { |
| 1921 |
1/2✓ Branch 0 taken 8683 times.
✗ Branch 1 not taken.
|
8683 | Item_func *func = dynamic_cast<Item_func *>(value_item); |
| 1922 | 8683 | Item *possible_const = value_item; | |
| 1923 | |||
| 1924 |
6/6✓ Branch 0 taken 2125 times.
✓ Branch 1 taken 6558 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 2114 times.
✓ Branch 4 taken 2122 times.
✓ Branch 5 taken 6561 times.
|
8694 | if (func && (func->functype() == Item_func::COLLATE_FUNC || |
| 1925 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
|
11 | func->functype() == Item_func::NEG_FUNC)) { |
| 1926 | /* | ||
| 1927 | The value is not a literal constant. Accept it if it's a | ||
| 1928 | COLLATE_FUNC or a NEG_FUNC wrapping a literal constant. | ||
| 1929 | */ | ||
| 1930 | 2122 | possible_const = func->key_item(); | |
| 1931 | } | ||
| 1932 | |||
| 1933 | /* | ||
| 1934 | There should now be no constant items which are functions left, | ||
| 1935 | (e.g. like TIME '1'), since none such are generated by subst_spvars() and | ||
| 1936 | sp_get_item_value(), which is where NAME_CONST calls are generated | ||
| 1937 | internally for the binary log: hence the second predicate below. If user | ||
| 1938 | applications try to use such constructs, or any non-constant contents for | ||
| 1939 | NAME_CONST's value argument (#2), we generate an error. | ||
| 1940 | */ | ||
| 1941 |
2/2✓ Branch 0 taken 8676 times.
✓ Branch 1 taken 7 times.
|
17359 | valid_args = (possible_const->basic_const_item() && |
| 1942 |
1/2✓ Branch 0 taken 8676 times.
✗ Branch 1 not taken.
|
8676 | possible_const->type() != FUNC_ITEM); |
| 1943 | } | ||
| 1944 | |||
| 1945 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8676 times.
|
8686 | if (!valid_args) { |
| 1946 | 10 | my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); | |
| 1947 | 10 | return true; | |
| 1948 | } | ||
| 1949 | |||
| 1950 | 8676 | return false; | |
| 1951 | } | ||
| 1952 | |||
| 1953 | 8355 | Item::Type Item_name_const::type() const { | |
| 1954 | /* | ||
| 1955 | As | ||
| 1956 | 1. one can try to create the Item_name_const passing non-constant | ||
| 1957 | arguments, although it's incorrect and | ||
| 1958 | 2. the type() method can be called before the fix_fields() to get | ||
| 1959 | type information for a further type cast, e.g. | ||
| 1960 | if (item->type() == FIELD_ITEM) | ||
| 1961 | ((Item_field *) item)->... | ||
| 1962 | we return NULL_ITEM in the case to avoid wrong casting. | ||
| 1963 | |||
| 1964 | valid_args guarantees value_item->basic_const_item(); if type is | ||
| 1965 | FUNC_ITEM, then we have a fudged item_func_neg() on our hands | ||
| 1966 | and return the underlying type. | ||
| 1967 | For Item_func_set_collation() | ||
| 1968 | e.g. NAME_CONST('name', 'value' COLLATE collation) we return its | ||
| 1969 | 'value' argument type. | ||
| 1970 | */ | ||
| 1971 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8355 times.
|
8355 | if (!valid_args) return NULL_ITEM; |
| 1972 | 8355 | Item::Type value_type = value_item->type(); | |
| 1973 |
2/2✓ Branch 0 taken 2224 times.
✓ Branch 1 taken 6131 times.
|
8355 | if (value_type == FUNC_ITEM) { |
| 1974 | /* | ||
| 1975 | The second argument of NAME_CONST('name', 'value') must be | ||
| 1976 | a simple constant item or a NEG_FUNC/COLLATE_FUNC. | ||
| 1977 | */ | ||
| 1978 | 2224 | Item_func *func = down_cast<Item_func *>(value_item); | |
| 1979 |
3/4✓ Branch 0 taken 2203 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2203 times.
|
2224 | assert(func->functype() == Item_func::NEG_FUNC || |
| 1980 | func->functype() == Item_func::COLLATE_FUNC); | ||
| 1981 | 2224 | return func->key_item()->type(); | |
| 1982 | } | ||
| 1983 | 6131 | return value_type; | |
| 1984 | } | ||
| 1985 | |||
| 1986 | 8653 | bool Item_name_const::fix_fields(THD *thd, Item **) { | |
| 1987 | char buf[128]; | ||
| 1988 | String *tmp; | ||
| 1989 | 8653 | String s(buf, sizeof(buf), &my_charset_bin); | |
| 1990 | 8653 | s.length(0); | |
| 1991 | |||
| 1992 |
1/2✓ Branch 0 taken 8653 times.
✗ Branch 1 not taken.
|
8653 | if (value_item->fix_fields(thd, &value_item) || |
| 1993 |
4/8✓ Branch 0 taken 8653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8653 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8653 times.
✗ Branch 7 not taken.
|
8653 | name_item->fix_fields(thd, &name_item) || !value_item->const_item() || |
| 1994 |
4/8✓ Branch 0 taken 8653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8653 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8653 times.
|
25959 | !name_item->const_item() || |
| 1995 |
2/4✓ Branch 0 taken 8653 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8653 times.
|
8653 | !(tmp = name_item->val_str(&s))) // Can't have a NULL name |
| 1996 | { | ||
| 1997 | ✗ | my_error(ER_RESERVED_SYNTAX, MYF(0), "NAME_CONST"); | |
| 1998 | ✗ | return true; | |
| 1999 | } | ||
| 2000 |
2/2✓ Branch 0 taken 8650 times.
✓ Branch 1 taken 3 times.
|
8653 | if (item_name.is_autogenerated()) { |
| 2001 |
1/2✓ Branch 0 taken 8650 times.
✗ Branch 1 not taken.
|
8650 | item_name.copy(tmp->ptr(), (uint)tmp->length(), system_charset_info); |
| 2002 | } | ||
| 2003 | 8653 | collation.set(value_item->collation.collation, | |
| 2004 | 8653 | value_item->collation.derivation, | |
| 2005 | 8653 | value_item->collation.repertoire); | |
| 2006 | 8653 | set_data_type(value_item->data_type()); | |
| 2007 | 8653 | max_length = value_item->max_length; | |
| 2008 | 8653 | decimals = value_item->decimals; | |
| 2009 | 8653 | fixed = true; | |
| 2010 | 8653 | return false; | |
| 2011 | 8653 | } | |
| 2012 | |||
| 2013 | ✗ | void Item_name_const::print(const THD *thd, String *str, | |
| 2014 | enum_query_type query_type) const { | ||
| 2015 | ✗ | str->append(STRING_WITH_LEN("NAME_CONST(")); | |
| 2016 | ✗ | name_item->print(thd, str, query_type); | |
| 2017 | ✗ | str->append(','); | |
| 2018 | ✗ | value_item->print(thd, str, query_type); | |
| 2019 | ✗ | str->append(')'); | |
| 2020 | } | ||
| 2021 | |||
| 2022 | /* | ||
| 2023 | need a special class to adjust printing : references to aggregate functions | ||
| 2024 | must not be printed as refs because the aggregate functions that are added to | ||
| 2025 | the front of select list are not printed as well. | ||
| 2026 | */ | ||
| 2027 | class Item_aggregate_ref : public Item_ref { | ||
| 2028 | public: | ||
| 2029 | 318599 | Item_aggregate_ref(Name_resolution_context *context_arg, Item **item, | |
| 2030 | const char *db_name_arg, const char *table_name_arg, | ||
| 2031 | const char *field_name_arg, Query_block *depended_from_arg) | ||
| 2032 | 318599 | : Item_ref(context_arg, item, db_name_arg, table_name_arg, | |
| 2033 | 318599 | field_name_arg) { | |
| 2034 | 318599 | depended_from = depended_from_arg; | |
| 2035 | 318599 | } | |
| 2036 | |||
| 2037 | 180423 | void print(const THD *thd, String *str, | |
| 2038 | enum_query_type query_type) const override { | ||
| 2039 |
1/2✓ Branch 0 taken 180423 times.
✗ Branch 1 not taken.
|
180423 | if (ref) |
| 2040 | 180423 | (*ref)->print(thd, str, query_type); | |
| 2041 | else | ||
| 2042 | ✗ | Item_ident::print(thd, str, query_type); | |
| 2043 | 180423 | } | |
| 2044 | 231888 | Ref_Type ref_type() const override { return AGGREGATE_REF; } | |
| 2045 | |||
| 2046 | /** | ||
| 2047 | Walker processor used by Query_block::transform_grouped_to_derived to | ||
| 2048 | replace an aggregate's reference to one in the new derived table's (hidden) | ||
| 2049 | select list. | ||
| 2050 | |||
| 2051 | @param arg An info object of type Item::Aggregate_ref_update | ||
| 2052 | @returns false | ||
| 2053 | */ | ||
| 2054 | ✗ | bool update_aggr_refs(uchar *arg) override { | |
| 2055 | ✗ | auto *info = pointer_cast<Item::Aggregate_ref_update *>(arg); | |
| 2056 | ✗ | if (*ref != info->m_target) return false; | |
| 2057 | ✗ | ref = info->m_owner->add_hidden_item(info->m_target); | |
| 2058 | ✗ | return false; | |
| 2059 | } | ||
| 2060 | }; | ||
| 2061 | |||
| 2062 | /** | ||
| 2063 | 1. Move SUM items out from item tree and replace with reference. | ||
| 2064 | |||
| 2065 | The general goal of this is to get a list of group aggregates, and window | ||
| 2066 | functions, and their arguments, so that the code which manages internal tmp | ||
| 2067 | tables (creation, row copying) has a list of all aggregates (which require | ||
| 2068 | special management) and a list of their arguments (which must be carried | ||
| 2069 | from tmp table to tmp table until the aggregate can be computed). | ||
| 2070 | |||
| 2071 | 2. Move scalar subqueries out of the item tree and replace with reference | ||
| 2072 | when used in arguments to window functions for similar reasons (tmp tables). | ||
| 2073 | |||
| 2074 | @param thd Current session | ||
| 2075 | @param ref_item_array Pointer to array of reference fields | ||
| 2076 | @param fields All fields in select | ||
| 2077 | @param ref Pointer to item. If nullptr, get it from | ||
| 2078 | Item_sum::referenced_by[]. | ||
| 2079 | @param skip_registered <=> function be must skipped for registered SUM items | ||
| 2080 | |||
| 2081 | All found SUM items are added FIRST in the fields list and | ||
| 2082 | we replace the item with a reference. | ||
| 2083 | |||
| 2084 | thd->fatal_error() may be called if we are out of memory | ||
| 2085 | |||
| 2086 | The logic of skip_registered is: | ||
| 2087 | |||
| 2088 | - split_sum_func() is called when an aggregate is part of a bigger | ||
| 2089 | expression, example: '1+max()'. | ||
| 2090 | |||
| 2091 | - an Item_sum has referenced_by[0]!=nullptr when it is a group aggregate | ||
| 2092 | located in a subquery but aggregating in a more outer query. | ||
| 2093 | |||
| 2094 | - this referenced_by is necessary because for such aggregates, there are | ||
| 2095 | two phases: | ||
| 2096 | |||
| 2097 | - fix_fields() is called by the subquery, which puts the item into the | ||
| 2098 | outer Query_block::inner_sum_func_list. | ||
| 2099 | |||
| 2100 | - the outer query scans that list, calls split_sum_func2(), it | ||
| 2101 | replaces the aggregate with an Item_ref, so it needs to correct the | ||
| 2102 | pointer-to-aggregate held by the '+' item; so it needs access to the | ||
| 2103 | pointer; this is possible because fix_fields() has stored the | ||
| 2104 | address of this pointer into referenced_by[0]. | ||
| 2105 | |||
| 2106 | - So when we call split_sum_func for any aggregate, if we are in the | ||
| 2107 | subquery, we do not want to modify the outer-aggregated aggregates, and | ||
| 2108 | as those are detectable because they have referenced_by[0]!=0: we pass | ||
| 2109 | 'skip_registered=true'. | ||
| 2110 | |||
| 2111 | - On the other hand, if we are in the outer query and scan | ||
| 2112 | inner_sum_func_list, it's time to modify the aggregate which was | ||
| 2113 | skipped by the subquery, so we pass 'skip_registered=false'. | ||
| 2114 | |||
| 2115 | - Finally, if the subquery was transformed with IN-to-EXISTS, a new | ||
| 2116 | HAVING condition may have been added, which contains an Item_ref to the | ||
| 2117 | same Item_sum; that makes a second pointer, referenced_by[1], | ||
| 2118 | to remember. | ||
| 2119 | @todo rename skip_registered to some name which better evokes | ||
| 2120 | "outer-ness" of the item; subquery_none exercises this function | ||
| 2121 | (Bug#11762); and rename referenced_by too, as it's set only for | ||
| 2122 | outer-aggregated items. | ||
| 2123 | |||
| 2124 | Examples of 1): | ||
| 2125 | |||
| 2126 | (1) SELECT a+FIRST_VALUE(b*SUM(c/d)) OVER (...) | ||
| 2127 | |||
| 2128 | Assume we have done fix_fields() on this SELECT list, which list is so far | ||
| 2129 | only '+'. This '+' contains a WF (and a group aggregate function), so the | ||
| 2130 | resolver (generally, Query_block::prepare()) calls Item::split_sum_func2 on | ||
| 2131 | the '+'; as this '+' is neither a WF nor a group aggregate, but contains | ||
| 2132 | some, it calls Item_func::split_sum_func which calls Item::split_sum_func2 on | ||
| 2133 | every argument of the '+': | ||
| 2134 | |||
| 2135 | - for 'a', it adds it to 'fields' as a hidden item | ||
| 2136 | |||
| 2137 | - then the FIRST_VALUE wf is added as a hidden item; this is necessary so | ||
| 2138 | that create_tmp_table() and copy_funcs can spot the WF. | ||
| 2139 | |||
| 2140 | - next, for FIRST_VALUE: it is a WF, so its Item_sum::split_sum_func is | ||
| 2141 | called, as its arguments need to be added as hidden items so they can get | ||
| 2142 | carried forward between the tmp tables. This split_sum_func calls | ||
| 2143 | Item::split_sum_func2 on its argument (the '*'); this | ||
| 2144 | '*' is not a group aggregate but contains one, so its | ||
| 2145 | Item_func::split_sum_func is called, which calls Item::split_sum_func2 on | ||
| 2146 | every argument of the '*': | ||
| 2147 | - for 'b', adds it to 'fields' as a hidden item | ||
| 2148 | - for SUM: it is a group aggregate (and doesn't contain any WF) so it | ||
| 2149 | adds it to 'fields' as a hidden item. | ||
| 2150 | |||
| 2151 | So we finally have, in 'fields': | ||
| 2152 | |||
| 2153 | SUM, b, FIRST_VALUE, a, + | ||
| 2154 | |||
| 2155 | Each time we add a hidden item we re-point its parent to the hidden item | ||
| 2156 | using an Item_aggregate_ref. For example, the args[0] of '+' is made to point | ||
| 2157 | to an Item_aggregate_ref which points to the hidden 'a'. | ||
| 2158 | |||
| 2159 | Examples of 2): | ||
| 2160 | |||
| 2161 | SELECT LAST_VALUE((SELECT upper.j FROM t1 LIMIT 1)) OVER (ORDER BY i) | ||
| 2162 | FROM t1 AS upper; | ||
| 2163 | */ | ||
| 2164 | |||
| 2165 | 757710 | void Item::split_sum_func2(THD *thd, Ref_item_array ref_item_array, | |
| 2166 | mem_root_deque<Item *> *fields, Item **ref, | ||
| 2167 | bool skip_registered) { | ||
| 2168 |
1/2✓ Branch 0 taken 757710 times.
✗ Branch 1 not taken.
|
757710 | DBUG_TRACE; |
| 2169 | /* An item of type Item_sum is registered <=> referenced_by[0] != 0 */ | ||
| 2170 |
6/8✓ Branch 0 taken 757710 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315225 times.
✓ Branch 3 taken 442485 times.
✓ Branch 4 taken 315140 times.
✓ Branch 5 taken 85 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 757710 times.
|
1072850 | if (type() == SUM_FUNC_ITEM && skip_registered && |
| 2171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 315140 times.
|
315140 | (down_cast<Item_sum *>(this))->referenced_by[0]) |
| 2172 | ✗ | return; | |
| 2173 | |||
| 2174 | // 'sum_func' means a group aggregate function | ||
| 2175 |
5/6✓ Branch 0 taken 757710 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315225 times.
✓ Branch 3 taken 442485 times.
✓ Branch 4 taken 315035 times.
✓ Branch 5 taken 190 times.
|
757710 | const bool is_sum_func = type() == SUM_FUNC_ITEM && !m_is_window_function; |
| 2176 |
4/4✓ Branch 0 taken 159925 times.
✓ Branch 1 taken 282750 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 159900 times.
|
442675 | if ((!is_sum_func && has_aggregation() && !m_is_window_function) || |
| 2177 |
4/4✓ Branch 0 taken 597620 times.
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 597585 times.
✓ Branch 3 taken 35 times.
|
597810 | (!m_is_window_function && has_wf()) || |
| 2178 |
6/8✓ Branch 0 taken 597775 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40017 times.
✓ Branch 3 taken 557758 times.
✓ Branch 4 taken 40017 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 40000 times.
✓ Branch 7 taken 17 times.
|
597775 | (type() == FUNC_ITEM && ((down_cast<Item_func *>(this))->functype() == |
| 2179 | 40000 | Item_func::ISNOTNULLTEST_FUNC || | |
| 2180 |
3/4✓ Branch 0 taken 40000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39996 times.
✓ Branch 3 taken 4 times.
|
40000 | (down_cast<Item_func *>(this))->functype() == |
| 2181 |
4/4✓ Branch 0 taken 442675 times.
✓ Branch 1 taken 315035 times.
✓ Branch 2 taken 159970 times.
✓ Branch 3 taken 597740 times.
|
1515420 | Item_func::TRIG_COND_FUNC)) || |
| 2182 |
3/4✓ Branch 0 taken 597754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 597740 times.
|
597754 | type() == ROW_ITEM) { |
| 2183 | // Do not add item to hidden list; possibly split it | ||
| 2184 |
1/2✓ Branch 0 taken 159970 times.
✗ Branch 1 not taken.
|
159970 | split_sum_func(thd, ref_item_array, fields); |
| 2185 |
4/6✓ Branch 0 taken 597740 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282515 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3505 times.
✓ Branch 5 taken 279010 times.
|
880255 | } else if ((type() == SUM_FUNC_ITEM || !const_for_execution()) && // (1) |
| 2186 |
3/4✓ Branch 0 taken 318730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 318729 times.
|
318730 | (type() != SUBSELECT_ITEM || // (2) |
| 2187 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | (down_cast<Item_subselect *>(this)->substype() == |
| 2188 | 1 | Item_subselect::SINGLEROW_SUBS && | |
| 2189 | 1 | down_cast<Item_subselect *>(this) | |
| 2190 | 1 | ->unit->first_query_block() | |
| 2191 |
6/8✓ Branch 0 taken 282515 times.
✓ Branch 1 taken 315225 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 318599 times.
✓ Branch 7 taken 279141 times.
|
1195481 | ->single_visible_field() != nullptr)) && |
| 2192 |
3/4✓ Branch 0 taken 318730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
✓ Branch 3 taken 318597 times.
|
318730 | (type() != REF_ITEM || // (3) |
| 2193 |
3/4✓ Branch 0 taken 133 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 131 times.
|
133 | (down_cast<Item_ref *>(this))->ref_type() == |
| 2194 | Item_ref::VIEW_REF)) { | ||
| 2195 | /* | ||
| 2196 | (1) Replace item with a reference so that we can easily calculate | ||
| 2197 | it (in case of sum functions) or copy it (in case of fields) | ||
| 2198 | |||
| 2199 | The test above is to ensure we don't do a reference for things | ||
| 2200 | that are constants (INNER_TABLE_BIT is in effect a constant) | ||
| 2201 | or already referenced (for example an item in HAVING) | ||
| 2202 | |||
| 2203 | (2) In order to handle queries like: | ||
| 2204 | SELECT FIRST_VALUE((SELECT .. FROM .. LIMIT 1)) OVER (..) FROM ...; | ||
| 2205 | we need to move subselects to hidden fields too. But since window | ||
| 2206 | functions accept only single-row and single-column subqueries other | ||
| 2207 | types are excluded. | ||
| 2208 | Indeed, a subquery of another type is wrapped in Item_in_optimizer at this | ||
| 2209 | stage, so when splitting Item_in_optimizer, if we added the underlying | ||
| 2210 | Item_subselect to "fields" below it would be later evaluated by | ||
| 2211 | copy_funcs() (in tmp table processing), which would be incorrect as the | ||
| 2212 | Item_subselect cannot be evaluated - as it must always be evaluated | ||
| 2213 | through its parent Item_in_optimizer. | ||
| 2214 | |||
| 2215 | (3) Exception from (1) is Item_view_ref which we need to wrap in | ||
| 2216 | Item_ref to allow fields from view being stored in tmp table. | ||
| 2217 | */ | ||
| 2218 |
3/8✓ Branch 0 taken 318599 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318599 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 318599 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
318599 | DBUG_PRINT("info", ("replacing %s with reference", item_name.ptr())); |
| 2219 | |||
| 2220 | 318599 | const bool old_hidden = hidden; // May be overwritten below. | |
| 2221 | |||
| 2222 | // See if the item is already there. If it's not there | ||
| 2223 | // (the common case), we put it at the end. | ||
| 2224 | // | ||
| 2225 | // However, if a scalar-subquery-to-derived rewrite needed to process | ||
| 2226 | // a HAVING item, we might already be there (as a visible item). | ||
| 2227 | // If so, we must not add ourselves twice, or we'd overwrite the hidden | ||
| 2228 | // flag. | ||
| 2229 | uint el = | ||
| 2230 |
1/2✓ Branch 0 taken 318599 times.
✗ Branch 1 not taken.
|
318599 | std::find(&ref_item_array[0], &ref_item_array[fields->size()], this) - |
| 2231 | 318599 | &ref_item_array[0]; | |
| 2232 |
2/2✓ Branch 0 taken 318597 times.
✓ Branch 1 taken 2 times.
|
318599 | if (el == fields->size()) { |
| 2233 | // Was not there from before, so add ourselves as a hidden item. | ||
| 2234 | 318597 | ref_item_array[el] = this; | |
| 2235 | // Should also be absent from 'fields', for consistency. | ||
| 2236 |
6/12✓ Branch 0 taken 318597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318597 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 318597 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 318597 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 318597 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 318597 times.
|
318597 | assert(std::find(fields->begin(), fields->end(), this) == fields->end()); |
| 2237 |
1/2✓ Branch 0 taken 318597 times.
✗ Branch 1 not taken.
|
318597 | fields->push_front(this); |
| 2238 | 318597 | hidden = true; | |
| 2239 | } else { | ||
| 2240 |
6/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
|
2 | assert(std::find(fields->begin(), fields->end(), this) != fields->end()); |
| 2241 | } | ||
| 2242 | |||
| 2243 | Query_block *base_query_block; | ||
| 2244 | 318599 | Query_block *depended_from = nullptr; | |
| 2245 |
7/8✓ Branch 0 taken 318599 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315225 times.
✓ Branch 3 taken 3374 times.
✓ Branch 4 taken 315035 times.
✓ Branch 5 taken 190 times.
✓ Branch 6 taken 315035 times.
✓ Branch 7 taken 3564 times.
|
318599 | if (type() == SUM_FUNC_ITEM && !m_is_window_function) { |
| 2246 | 315035 | Item_sum *const item = down_cast<Item_sum *>(this); | |
| 2247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 315035 times.
|
315035 | assert(thd->lex->current_query_block() == item->aggr_query_block); |
| 2248 | 315035 | base_query_block = item->base_query_block; | |
| 2249 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 314950 times.
|
315035 | if (item->aggr_query_block != base_query_block) |
| 2250 | 85 | depended_from = item->aggr_query_block; | |
| 2251 | } else { | ||
| 2252 | 3564 | base_query_block = thd->lex->current_query_block(); | |
| 2253 | } | ||
| 2254 | |||
| 2255 | Item_aggregate_ref *const item_ref = new Item_aggregate_ref( | ||
| 2256 | 318599 | &base_query_block->context, &ref_item_array[el], nullptr, nullptr, | |
| 2257 |
2/4✓ Branch 0 taken 318599 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318599 times.
✗ Branch 3 not taken.
|
318599 | item_name.ptr(), depended_from); |
| 2258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 318599 times.
|
318599 | if (!item_ref) return; /* purecov: inspected */ |
| 2259 | 318599 | item_ref->hidden = old_hidden; | |
| 2260 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 318514 times.
|
318599 | if (ref == nullptr) { |
| 2261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | assert(is_sum_func); |
| 2262 | // Let 'ref' be the two elements of referenced_by[]. | ||
| 2263 | 85 | ref = down_cast<Item_sum *>(this)->referenced_by[1]; | |
| 2264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | if (ref != nullptr) *ref = item_ref; |
| 2265 | 85 | ref = down_cast<Item_sum *>(this)->referenced_by[0]; | |
| 2266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | assert(ref); |
| 2267 | } | ||
| 2268 | // WL#6570 remove-after-qa | ||
| 2269 |
3/4✓ Branch 0 taken 2835 times.
✓ Branch 1 taken 315764 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2835 times.
|
318599 | assert(thd->stmt_arena->is_regular() || !thd->lex->is_exec_started()); |
| 2270 | 318599 | *ref = item_ref; | |
| 2271 | |||
| 2272 | /* | ||
| 2273 | A WF must both be added to hidden list (done above), and be split so its | ||
| 2274 | arguments are added into the hidden list (done below): | ||
| 2275 | */ | ||
| 2276 |
3/4✓ Branch 0 taken 190 times.
✓ Branch 1 taken 318409 times.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
|
318599 | if (m_is_window_function) split_sum_func(thd, ref_item_array, fields); |
| 2277 | } | ||
| 2278 |
1/2✓ Branch 0 taken 757710 times.
✗ Branch 1 not taken.
|
757710 | } |
| 2279 | |||
| 2280 | 2624986 | static bool left_is_superset(DTCollation *left, DTCollation *right) { | |
| 2281 | /* Allow convert to Unicode */ | ||
| 2282 |
2/2✓ Branch 0 taken 2437594 times.
✓ Branch 1 taken 187392 times.
|
2624986 | if (left->collation->state & MY_CS_UNICODE && |
| 2283 |
2/2✓ Branch 0 taken 432711 times.
✓ Branch 1 taken 2004883 times.
|
2437594 | (left->derivation < right->derivation || |
| 2284 |
2/2✓ Branch 0 taken 302568 times.
✓ Branch 1 taken 130143 times.
|
432711 | (left->derivation == right->derivation && |
| 2285 |
2/2✓ Branch 0 taken 214867 times.
✓ Branch 1 taken 87701 times.
|
302568 | (!(right->collation->state & MY_CS_UNICODE) || |
| 2286 | /* The code below makes 4-byte utf8 a superset over 3-byte utf8 */ | ||
| 2287 |
2/2✓ Branch 0 taken 140502 times.
✓ Branch 1 taken 74365 times.
|
214867 | (left->collation->state & MY_CS_UNICODE_SUPPLEMENT && |
| 2288 |
2/2✓ Branch 0 taken 140500 times.
✓ Branch 1 taken 2 times.
|
140502 | !(right->collation->state & MY_CS_UNICODE_SUPPLEMENT) && |
| 2289 |
2/2✓ Branch 0 taken 140471 times.
✓ Branch 1 taken 29 times.
|
140500 | left->collation->mbmaxlen > right->collation->mbmaxlen && |
| 2290 |
2/2✓ Branch 0 taken 140459 times.
✓ Branch 1 taken 12 times.
|
140471 | left->collation->mbminlen == right->collation->mbminlen))))) |
| 2291 | 2233043 | return true; | |
| 2292 | /* Allow convert from any Unicode to utf32 or utf8mb4 */ | ||
| 2293 |
2/2✓ Branch 0 taken 102004 times.
✓ Branch 1 taken 289939 times.
|
391943 | if (test_all_bits(left->collation->state, |
| 2294 | 102004 | MY_CS_UNICODE | MY_CS_UNICODE_SUPPLEMENT) && | |
| 2295 |
2/2✓ Branch 0 taken 64278 times.
✓ Branch 1 taken 37726 times.
|
102004 | right->collation->state & MY_CS_UNICODE && |
| 2296 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 64235 times.
|
64278 | left->derivation == right->derivation) |
| 2297 | 43 | return true; | |
| 2298 | /* Allow convert from ASCII */ | ||
| 2299 |
2/2✓ Branch 0 taken 179402 times.
✓ Branch 1 taken 212498 times.
|
391900 | if (right->repertoire == MY_REPERTOIRE_ASCII && |
| 2300 |
2/2✓ Branch 0 taken 89111 times.
✓ Branch 1 taken 90291 times.
|
179402 | (left->derivation < right->derivation || |
| 2301 |
2/2✓ Branch 0 taken 30002 times.
✓ Branch 1 taken 59109 times.
|
89111 | (left->derivation == right->derivation && |
| 2302 |
2/2✓ Branch 0 taken 29935 times.
✓ Branch 1 taken 67 times.
|
30002 | !(left->repertoire == MY_REPERTOIRE_ASCII)))) |
| 2303 | 120226 | return true; | |
| 2304 | /* Disallow conversion otherwise */ | ||
| 2305 | 271674 | return false; | |
| 2306 | } | ||
| 2307 | |||
| 2308 | /** | ||
| 2309 | Aggregate two collations together taking | ||
| 2310 | into account their coercibility (aka derivation):. | ||
| 2311 | |||
| 2312 | 0 == DERIVATION_EXPLICIT - an explicitly written COLLATE clause @n | ||
| 2313 | 1 == DERIVATION_NONE - a mix of two different collations @n | ||
| 2314 | 2 == DERIVATION_IMPLICIT - a column @n | ||
| 2315 | 3 == DERIVATION_COERCIBLE - a string constant. | ||
| 2316 | |||
| 2317 | The most important rules are: | ||
| 2318 | -# If collations are the same: | ||
| 2319 | chose this collation, and the strongest derivation. | ||
| 2320 | -# If collations are different: | ||
| 2321 | - Character sets may differ, but only if conversion without | ||
| 2322 | data loss is possible. The caller provides flags whether | ||
| 2323 | character set conversion attempts should be done. If no | ||
| 2324 | flags are substituted, then the character sets must be the same. | ||
| 2325 | Currently processed flags are: | ||
| 2326 | MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset | ||
| 2327 | MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value | ||
| 2328 | - two EXPLICIT collations produce an error, e.g. this is wrong: | ||
| 2329 | CONCAT(expr1 collate latin1_swedish_ci, expr2 collate latin1_german_ci) | ||
| 2330 | - the side with smaller derivation value wins, | ||
| 2331 | i.e. a column is stronger than a string constant, | ||
| 2332 | an explicit COLLATE clause is stronger than a column. | ||
| 2333 | - if derivations are the same, we have DERIVATION_NONE, | ||
| 2334 | we'll wait for an explicit COLLATE clause which possibly can | ||
| 2335 | come from another argument later: for example, this is valid, | ||
| 2336 | but we don't know yet when collecting the first two arguments: | ||
| 2337 | @code | ||
| 2338 | CONCAT(latin1_swedish_ci_column, | ||
| 2339 | latin1_german1_ci_column, | ||
| 2340 | expr COLLATE latin1_german2_ci) | ||
| 2341 | @endcode | ||
| 2342 | |||
| 2343 | @retval true If the two collations are incompatible and cannot be aggregated. | ||
| 2344 | |||
| 2345 | @retval false If the two collations can be aggregated, possibly with | ||
| 2346 | DERIVATION_NONE to indicate that they need a third explicit collation as a | ||
| 2347 | tiebreaker. | ||
| 2348 | |||
| 2349 | */ | ||
| 2350 | |||
| 2351 | 32887213 | bool DTCollation::aggregate(DTCollation &dt, uint flags) { | |
| 2352 |
2/2✓ Branch 0 taken 5238064 times.
✓ Branch 1 taken 27649161 times.
|
32887213 | if (!my_charset_same(collation, dt.collation)) { |
| 2353 | /* | ||
| 2354 | We do allow to use binary strings (like BLOBS) | ||
| 2355 | together with character strings. | ||
| 2356 | Binaries have more precedence than a character | ||
| 2357 | string of the same derivation. | ||
| 2358 | */ | ||
| 2359 |
2/2✓ Branch 0 taken 2484291 times.
✓ Branch 1 taken 2753773 times.
|
5238064 | if (collation == &my_charset_bin) { |
| 2360 |
2/2✓ Branch 0 taken 2431762 times.
✓ Branch 1 taken 52529 times.
|
2484291 | if (derivation <= dt.derivation) |
| 2361 | ; // Do nothing | ||
| 2362 | else { | ||
| 2363 | 2431762 | set(dt); | |
| 2364 | } | ||
| 2365 |
2/2✓ Branch 0 taken 400339 times.
✓ Branch 1 taken 2353434 times.
|
2753773 | } else if (dt.collation == &my_charset_bin) { |
| 2366 |
2/2✓ Branch 0 taken 3576 times.
✓ Branch 1 taken 396763 times.
|
400339 | if (dt.derivation <= derivation) { |
| 2367 | 3576 | set(dt); | |
| 2368 | } | ||
| 2369 |
6/6✓ Branch 0 taken 2353433 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2081880 times.
✓ Branch 3 taken 271553 times.
✓ Branch 4 taken 271553 times.
✓ Branch 5 taken 2081881 times.
|
4706867 | } else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && |
| 2370 | 2353433 | left_is_superset(this, &dt)) { | |
| 2371 | // Do nothing | ||
| 2372 |
5/6✓ Branch 0 taken 271553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 271432 times.
✓ Branch 3 taken 121 times.
✓ Branch 4 taken 271432 times.
✓ Branch 5 taken 121 times.
|
543106 | } else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && |
| 2373 | 271553 | left_is_superset(&dt, this)) { | |
| 2374 | 271432 | set(dt); | |
| 2375 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | } else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) && |
| 2376 |
2/2✓ Branch 0 taken 82 times.
✓ Branch 1 taken 39 times.
|
121 | derivation < dt.derivation && |
| 2377 |
1/2✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
|
82 | dt.derivation >= DERIVATION_SYSCONST) { |
| 2378 | // Do nothing; | ||
| 2379 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | } else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) && |
| 2380 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 30 times.
|
39 | dt.derivation < derivation && |
| 2381 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | derivation >= DERIVATION_SYSCONST) { |
| 2382 | 9 | set(dt); | |
| 2383 | } else { | ||
| 2384 | // Cannot apply conversion | ||
| 2385 | 30 | set(&my_charset_bin, DERIVATION_NONE, (dt.repertoire | repertoire)); | |
| 2386 | 30 | return true; | |
| 2387 | } | ||
| 2388 |
2/2✓ Branch 0 taken 5224856 times.
✓ Branch 1 taken 22424305 times.
|
27649161 | } else if (derivation < dt.derivation) { |
| 2389 | // Do nothing | ||
| 2390 |
2/2✓ Branch 0 taken 176629 times.
✓ Branch 1 taken 5048227 times.
|
5224856 | } else if (dt.derivation < derivation) { |
| 2391 | 176629 | set(dt); | |
| 2392 | } else { | ||
| 2393 |
2/2✓ Branch 0 taken 57054 times.
✓ Branch 1 taken 4991173 times.
|
5048227 | if (collation == dt.collation) { |
| 2394 | // Do nothing | ||
| 2395 | } else { | ||
| 2396 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 57038 times.
|
57054 | if (derivation == DERIVATION_EXPLICIT) { |
| 2397 | 16 | set(nullptr, DERIVATION_NONE, 0); | |
| 2398 | 16 | return true; | |
| 2399 | } | ||
| 2400 | |||
| 2401 | // If we have two different binary collations for the same character set, | ||
| 2402 | // and none of them is explicit, we don't know which to choose. For | ||
| 2403 | // example: utf8mb4_bin is a binary padding collation, utf8mb4_0900_bin is | ||
| 2404 | // a binary non-padding collation. Cannot determine if the resulting | ||
| 2405 | // collation should be padding or non-padding, unless they are also | ||
| 2406 | // aggregated with a third explicit collation. | ||
| 2407 |
2/2✓ Branch 0 taken 8985 times.
✓ Branch 1 taken 48053 times.
|
57038 | if ((collation->state & MY_CS_BINSORT) && |
| 2408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8985 times.
|
8985 | (dt.collation->state & MY_CS_BINSORT)) { |
| 2409 | ✗ | set(DERIVATION_NONE); | |
| 2410 | ✗ | return false; | |
| 2411 | } | ||
| 2412 | |||
| 2413 | // When aggregating a binary and a non-binary collation for the same | ||
| 2414 | // character set, the binary collation is preferred. | ||
| 2415 |
2/2✓ Branch 0 taken 8985 times.
✓ Branch 1 taken 48053 times.
|
57038 | if (collation->state & MY_CS_BINSORT) return false; |
| 2416 |
2/2✓ Branch 0 taken 47867 times.
✓ Branch 1 taken 186 times.
|
48053 | if (dt.collation->state & MY_CS_BINSORT) { |
| 2417 | 47867 | set(dt); | |
| 2418 | 47867 | return false; | |
| 2419 | } | ||
| 2420 | const CHARSET_INFO *bin = | ||
| 2421 | 186 | get_charset_by_csname(collation->csname, MY_CS_BINSORT, MYF(0)); | |
| 2422 | 186 | set(bin, DERIVATION_NONE); | |
| 2423 | } | ||
| 2424 | } | ||
| 2425 | 32830317 | repertoire |= dt.repertoire; | |
| 2426 | 32830317 | return false; | |
| 2427 | } | ||
| 2428 | |||
| 2429 | /******************************/ | ||
| 2430 | 70 | static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, | |
| 2431 | const char *fname) { | ||
| 2432 | 140 | my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), c1.collation->m_coll_name, | |
| 2433 | 70 | c1.derivation_name(), c2.collation->m_coll_name, | |
| 2434 | c2.derivation_name(), fname); | ||
| 2435 | 70 | } | |
| 2436 | |||
| 2437 | 15 | static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3, | |
| 2438 | const char *fname) { | ||
| 2439 | 30 | my_error(ER_CANT_AGGREGATE_3COLLATIONS, MYF(0), c1.collation->m_coll_name, | |
| 2440 | 15 | c1.derivation_name(), c2.collation->m_coll_name, | |
| 2441 | 15 | c2.derivation_name(), c3.collation->m_coll_name, | |
| 2442 | c3.derivation_name(), fname); | ||
| 2443 | 15 | } | |
| 2444 | |||
| 2445 | 89 | static void my_coll_agg_error(Item **args, uint count, const char *fname, | |
| 2446 | int item_sep) { | ||
| 2447 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 19 times.
|
89 | if (count == 2) |
| 2448 | 70 | my_coll_agg_error(args[0]->collation, args[item_sep]->collation, fname); | |
| 2449 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
|
19 | else if (count == 3) |
| 2450 | 15 | my_coll_agg_error(args[0]->collation, args[item_sep]->collation, | |
| 2451 | 15 | args[2 * item_sep]->collation, fname); | |
| 2452 | else | ||
| 2453 | 4 | my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), fname); | |
| 2454 | 89 | } | |
| 2455 | |||
| 2456 | 21550710 | static bool agg_item_collations(DTCollation &c, const char *fname, Item **av, | |
| 2457 | uint count, uint flags, int item_sep) { | ||
| 2458 | uint i; | ||
| 2459 | Item **arg; | ||
| 2460 | 21550710 | bool unknown_cs = false; | |
| 2461 | |||
| 2462 | 21550710 | c.set(av[0]->collation); | |
| 2463 |
2/2✓ Branch 0 taken 18197891 times.
✓ Branch 1 taken 21550701 times.
|
39748592 | for (i = 1, arg = &av[item_sep]; i < count; i++, arg++) { |
| 2464 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 18197844 times.
|
18197891 | if (c.aggregate((*arg)->collation, flags)) { |
| 2465 |
3/4✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 16 times.
|
45 | if (c.derivation == DERIVATION_NONE && c.collation == &my_charset_bin) { |
| 2466 | 30 | unknown_cs = true; | |
| 2467 | 30 | continue; | |
| 2468 | } | ||
| 2469 | 15 | my_coll_agg_error(av, count, fname, item_sep); | |
| 2470 | 16 | return true; | |
| 2471 | } | ||
| 2472 | } | ||
| 2473 | |||
| 2474 |
4/4✓ Branch 0 taken 30 times.
✓ Branch 1 taken 21550671 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 4 times.
|
21550701 | if (unknown_cs && c.derivation != DERIVATION_EXPLICIT) { |
| 2475 | 26 | my_coll_agg_error(av, count, fname, item_sep); | |
| 2476 | 26 | return true; | |
| 2477 | } | ||
| 2478 | |||
| 2479 |
4/4✓ Branch 0 taken 7740498 times.
✓ Branch 1 taken 13810177 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 7740487 times.
|
21550675 | if ((flags & MY_COLL_DISALLOW_NONE) && c.derivation == DERIVATION_NONE) { |
| 2480 | 11 | my_coll_agg_error(av, count, fname, item_sep); | |
| 2481 | 11 | return true; | |
| 2482 | } | ||
| 2483 | |||
| 2484 | /* If all arguments were numbers, reset to @@collation_connection */ | ||
| 2485 |
4/4✓ Branch 0 taken 13810174 times.
✓ Branch 1 taken 7740490 times.
✓ Branch 2 taken 194236 times.
✓ Branch 3 taken 13615938 times.
|
21550664 | if (flags & MY_COLL_ALLOW_NUMERIC_CONV && c.derivation == DERIVATION_NUMERIC) |
| 2486 | 194236 | c.set(Item::default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_NUMERIC); | |
| 2487 | |||
| 2488 | 21550663 | return false; | |
| 2489 | } | ||
| 2490 | |||
| 2491 | 2749 | bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, | |
| 2492 | Item **av, uint count, uint flags) { | ||
| 2493 | 2749 | return (agg_item_collations(c, fname, av, count, | |
| 2494 | 2749 | flags | MY_COLL_DISALLOW_NONE, 1)); | |
| 2495 | } | ||
| 2496 | |||
| 2497 | 36237246 | bool agg_item_set_converter(DTCollation &coll, const char *fname, Item **args, | |
| 2498 | uint nargs, uint, int item_sep, bool only_consts) { | ||
| 2499 | 36237246 | Item *safe_args[2] = {nullptr, nullptr}; | |
| 2500 | |||
| 2501 | /* | ||
| 2502 | For better error reporting: save the first and the second argument. | ||
| 2503 | We need this only if the the number of args is 3 or 2: | ||
| 2504 | - for a longer argument list, "Illegal mix of collations" | ||
| 2505 | doesn't display each argument's characteristics. | ||
| 2506 | - if nargs is 1, then this error cannot happen. | ||
| 2507 | */ | ||
| 2508 |
4/4✓ Branch 0 taken 13048946 times.
✓ Branch 1 taken 23188300 times.
✓ Branch 2 taken 12375669 times.
✓ Branch 3 taken 673277 times.
|
36237246 | if (nargs >= 2 && nargs <= 3) { |
| 2509 | 12375669 | safe_args[0] = args[0]; | |
| 2510 | 12375669 | safe_args[1] = args[item_sep]; | |
| 2511 | } | ||
| 2512 | |||
| 2513 |
1/2✓ Branch 0 taken 36237228 times.
✗ Branch 1 not taken.
|
36237246 | THD *thd = current_thd; |
| 2514 | |||
| 2515 | uint i; | ||
| 2516 | Item **arg; | ||
| 2517 |
2/2✓ Branch 0 taken 54433742 times.
✓ Branch 1 taken 36237206 times.
|
90670948 | for (i = 0, arg = args; i < nargs; i++, arg += item_sep) { |
| 2518 | size_t dummy_offset; | ||
| 2519 | // If told so (from comparison code), only add converter for const values. | ||
| 2520 |
7/8✓ Branch 0 taken 32884544 times.
✓ Branch 1 taken 21549198 times.
✓ Branch 2 taken 32884555 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15354041 times.
✓ Branch 5 taken 17530514 times.
✓ Branch 6 taken 15354040 times.
✓ Branch 7 taken 39079713 times.
|
91679275 | if (only_consts && !(*arg)->const_item()) continue; |
| 2521 |
3/4✓ Branch 0 taken 39079716 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36760480 times.
✓ Branch 3 taken 2319236 times.
|
39079713 | if (!String::needs_conversion(1, (*arg)->collation.collation, |
| 2522 | coll.collation, &dummy_offset)) | ||
| 2523 | 36760480 | continue; | |
| 2524 | |||
| 2525 | /* | ||
| 2526 | No needs to add converter if an "arg" is NUMERIC or DATETIME | ||
| 2527 | value (which is pure ASCII) and at the same time target DTCollation | ||
| 2528 | is ASCII-compatible. For example, no needs to rewrite: | ||
| 2529 | SELECT * FROM t1 WHERE datetime_field = '2010-01-01'; | ||
| 2530 | to | ||
| 2531 | SELECT * FROM t1 WHERE CONVERT(datetime_field USING cs) = '2010-01-01'; | ||
| 2532 | |||
| 2533 | TODO: avoid conversion of any values with | ||
| 2534 | repertoire ASCII and 7bit-ASCII-compatible, | ||
| 2535 | not only numeric/datetime origin. | ||
| 2536 | */ | ||
| 2537 |
2/2✓ Branch 0 taken 485497 times.
✓ Branch 1 taken 1833739 times.
|
2319236 | if ((*arg)->collation.derivation == DERIVATION_NUMERIC && |
| 2538 |
1/2✓ Branch 0 taken 485497 times.
✗ Branch 1 not taken.
|
485497 | (*arg)->collation.repertoire == MY_REPERTOIRE_ASCII && |
| 2539 |
1/2✓ Branch 0 taken 485497 times.
✗ Branch 1 not taken.
|
485497 | !((*arg)->collation.collation->state & MY_CS_NONASCII) && |
| 2540 |
2/2✓ Branch 0 taken 485053 times.
✓ Branch 1 taken 444 times.
|
485497 | !(coll.collation->state & MY_CS_NONASCII)) |
| 2541 | 485053 | continue; | |
| 2542 | |||
| 2543 |
1/2✓ Branch 0 taken 1834185 times.
✗ Branch 1 not taken.
|
1834183 | Item *conv = (*arg)->safe_charset_converter(thd, coll.collation); |
| 2544 | // @todo - check why the constructors may return error | ||
| 2545 |
3/4✓ Branch 0 taken 1834185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1834183 times.
|
1834221 | if (thd->is_error()) return true; |
| 2546 |
2/2✓ Branch 0 taken 123 times.
✓ Branch 1 taken 1834060 times.
|
1834183 | if (conv == nullptr && |
| 2547 |
2/2✓ Branch 0 taken 87 times.
✓ Branch 1 taken 36 times.
|
123 | ((*arg)->collation.repertoire == MY_REPERTOIRE_ASCII)) |
| 2548 |
2/4✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
|
87 | conv = new Item_func_conv_charset(thd, *arg, coll.collation, true); |
| 2549 | |||
| 2550 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1834147 times.
|
1834183 | if (conv == nullptr) { |
| 2551 |
2/4✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
36 | if (nargs >= 2 && nargs <= 3) { |
| 2552 | /* restore the original arguments for better error message */ | ||
| 2553 | 36 | args[0] = safe_args[0]; | |
| 2554 | 36 | args[item_sep] = safe_args[1]; | |
| 2555 | } | ||
| 2556 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | my_coll_agg_error(args, nargs, fname, item_sep); |
| 2557 | 36 | return true; | |
| 2558 | } | ||
| 2559 | |||
| 2560 | // Update the Item pointer in-place | ||
| 2561 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1834144 times.
|
1834147 | if (thd->lex->is_exec_started()) |
| 2562 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | thd->change_item_tree(arg, conv); |
| 2563 | else | ||
| 2564 | 1834144 | *arg = conv; | |
| 2565 | |||
| 2566 |
1/2✓ Branch 0 taken 1834147 times.
✗ Branch 1 not taken.
|
1834147 | (*arg)->disable_constant_propagation(nullptr); |
| 2567 | |||
| 2568 |
2/4✓ Branch 0 taken 1834147 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1834147 times.
|
1834147 | if (conv->fix_fields(thd, arg)) return true; |
| 2569 | } | ||
| 2570 | |||
| 2571 | 36237206 | return false; | |
| 2572 | } | ||
| 2573 | |||
| 2574 | /* | ||
| 2575 | Collect arguments' character sets together. | ||
| 2576 | We allow to apply automatic character set conversion in some cases. | ||
| 2577 | The conditions when conversion is possible are: | ||
| 2578 | - arguments A and B have different charsets | ||
| 2579 | - A wins according to coercibility rules | ||
| 2580 | (i.e. a column is stronger than a string constant, | ||
| 2581 | an explicit COLLATE clause is stronger than a column) | ||
| 2582 | - character set of A is either superset for character set of B, | ||
| 2583 | or B is a string constant which can be converted into the | ||
| 2584 | character set of A without data loss. | ||
| 2585 | |||
| 2586 | If all of the above is true, then it's possible to convert | ||
| 2587 | B into the character set of A, and then compare according | ||
| 2588 | to the collation of A. | ||
| 2589 | |||
| 2590 | For functions with more than two arguments: | ||
| 2591 | |||
| 2592 | collect(A,B,C) ::= collect(collect(A,B),C) | ||
| 2593 | |||
| 2594 | When a character set conversion is needed, the respective Item pointer | ||
| 2595 | is updated in-place as a permanent transformation. | ||
| 2596 | |||
| 2597 | If the items are not consecutive (eg. args[2] and args[5]), use the | ||
| 2598 | item_sep argument, ie. | ||
| 2599 | |||
| 2600 | agg_item_charsets(coll, fname, &args[2], 2, flags, 3) | ||
| 2601 | */ | ||
| 2602 | |||
| 2603 | 21547962 | bool agg_item_charsets(DTCollation &coll, const char *fname, Item **args, | |
| 2604 | uint nargs, uint flags, int item_sep, bool only_consts) { | ||
| 2605 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 21547914 times.
|
21547962 | if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) |
| 2606 | 53 | return true; | |
| 2607 | 21547914 | return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep, | |
| 2608 | 21547915 | only_consts); | |
| 2609 | } | ||
| 2610 | |||
| 2611 | 17 | void Item_ident_for_show::make_field(Send_field *tmp_field) { | |
| 2612 | 17 | tmp_field->table_name = tmp_field->org_table_name = table_name; | |
| 2613 | 17 | tmp_field->db_name = db_name; | |
| 2614 | 17 | tmp_field->col_name = tmp_field->org_col_name = field->field_name; | |
| 2615 | 17 | tmp_field->charsetnr = field->charset()->number; | |
| 2616 | 17 | tmp_field->length = field->field_length; | |
| 2617 | 17 | tmp_field->type = field->type(); | |
| 2618 | 17 | tmp_field->flags = field->all_flags(); | |
| 2619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (field->table->is_nullable()) tmp_field->flags &= ~NOT_NULL_FLAG; |
| 2620 | 17 | tmp_field->decimals = field->decimals(); | |
| 2621 | 17 | tmp_field->field = false; | |
| 2622 | 17 | } | |
| 2623 | |||
| 2624 | 17 | bool Item_ident_for_show::fix_fields(THD *, Item **) { | |
| 2625 | 17 | set_nullable(field->is_nullable()); | |
| 2626 | 17 | decimals = field->decimals(); | |
| 2627 | 17 | unsigned_flag = field->is_flag_set(UNSIGNED_FLAG); | |
| 2628 | 17 | collation.set(field->charset(), field->derivation(), field->repertoire()); | |
| 2629 | 17 | set_data_type(field->type()); | |
| 2630 | 17 | max_length = char_to_byte_length_safe(field->char_length(), | |
| 2631 | 17 | collation.collation->mbmaxlen); | |
| 2632 | |||
| 2633 | 17 | fixed = true; | |
| 2634 | |||
| 2635 | 17 | return false; | |
| 2636 | } | ||
| 2637 | |||
| 2638 | /** | ||
| 2639 | Constructor used inside setup_wild(). | ||
| 2640 | Item is resolved after construction. | ||
| 2641 | Item is supposed to have lifetime same as statement it is created within. | ||
| 2642 | |||
| 2643 | @param thd thread context | ||
| 2644 | @param context_arg Name resolution context for this field | ||
| 2645 | @param tr Table reference, provides table and schema name | ||
| 2646 | @param f Field reference, provides field name and original table name | ||
| 2647 | */ | ||
| 2648 | |||
| 2649 | 16314984 | Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, | |
| 2650 | 16314984 | TABLE_LIST *tr, Field *f) | |
| 2651 | 16314984 | : Item_ident(context_arg, f->table->s->db.str, *f->table_name, | |
| 2652 | f->field_name), | ||
| 2653 | 16315563 | table_ref(tr), | |
| 2654 | 16315563 | field(nullptr), | |
| 2655 | 16315563 | item_equal(nullptr), | |
| 2656 | 16315563 | field_index(NO_FIELD_INDEX), | |
| 2657 | 16315563 | have_privileges(0), | |
| 2658 | 16314984 | any_privileges(false) { | |
| 2659 |
1/2✓ Branch 0 taken 16315022 times.
✗ Branch 1 not taken.
|
16315563 | set_field(f); |
| 2660 | |||
| 2661 | // Possibly override original names that were assigned from table reference: | ||
| 2662 |
2/2✓ Branch 0 taken 335617 times.
✓ Branch 1 taken 15979405 times.
|
16315022 | if (f->orig_table_name != nullptr) m_orig_table_name = f->orig_table_name; |
| 2663 |
2/2✓ Branch 0 taken 335617 times.
✓ Branch 1 taken 15979405 times.
|
16315022 | if (f->orig_db_name != nullptr) m_orig_db_name = f->orig_db_name; |
| 2664 | /* | ||
| 2665 | The field pointer may have shorter lifetime than the Item that is created | ||
| 2666 | here, so ensure the name is created in durable memory. | ||
| 2667 | */ | ||
| 2668 |
1/2✓ Branch 0 taken 16315237 times.
✗ Branch 1 not taken.
|
16315022 | m_orig_field_name = thd->mem_strdup(f->field_name); |
| 2669 | 16315237 | field_name = m_orig_field_name; | |
| 2670 | 16315237 | item_name.set(m_orig_field_name); | |
| 2671 | 16315623 | } | |
| 2672 | |||
| 2673 | /** | ||
| 2674 | Constructor used for internal information queries. | ||
| 2675 | |||
| 2676 | @param context_arg Name resolution context | ||
| 2677 | @param db_arg Schema name, may be NULL | ||
| 2678 | @param table_name_arg Table name, may be NULL if schema name is NULL | ||
| 2679 | @param field_name_arg Field name | ||
| 2680 | */ | ||
| 2681 | 2606 | Item_field::Item_field(Name_resolution_context *context_arg, const char *db_arg, | |
| 2682 | 2606 | const char *table_name_arg, const char *field_name_arg) | |
| 2683 | : Item_ident(context_arg, db_arg, table_name_arg, field_name_arg), | ||
| 2684 | 2606 | table_ref(nullptr), | |
| 2685 | 2606 | field(nullptr), | |
| 2686 | 2606 | item_equal(nullptr), | |
| 2687 | 2606 | field_index(NO_FIELD_INDEX), | |
| 2688 | 2606 | have_privileges(0), | |
| 2689 | 2606 | any_privileges(false) { | |
| 2690 |
1/2✓ Branch 0 taken 2606 times.
✗ Branch 1 not taken.
|
2606 | Query_block *select = current_thd->lex->current_query_block(); |
| 2691 | 2606 | collation.set(DERIVATION_IMPLICIT); | |
| 2692 |
2/4✓ Branch 0 taken 2606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2606 times.
✗ Branch 3 not taken.
|
2606 | if (select && select->parsing_place != CTX_HAVING) |
| 2693 | 2606 | select->select_n_where_fields++; | |
| 2694 | 2606 | } | |
| 2695 | |||
| 2696 | /** | ||
| 2697 | Used from parser to construct column references. | ||
| 2698 | |||
| 2699 | @param pos Parse context | ||
| 2700 | @param db_arg Schema name for column, may be NULL | ||
| 2701 | @param table_name_arg Table name for column, may be NULL if db_arg is NULL | ||
| 2702 | @param field_name_arg Column name, always given. | ||
| 2703 | */ | ||
| 2704 | 70121903 | Item_field::Item_field(const POS &pos, const char *db_arg, | |
| 2705 | 70121903 | const char *table_name_arg, const char *field_name_arg) | |
| 2706 | : Item_ident(pos, db_arg, table_name_arg, field_name_arg), | ||
| 2707 | 70122457 | table_ref(nullptr), | |
| 2708 | 70122457 | field(nullptr), | |
| 2709 | 70122457 | item_equal(nullptr), | |
| 2710 | 70122457 | field_index(NO_FIELD_INDEX), | |
| 2711 | 70122457 | have_privileges(0), | |
| 2712 | 70121903 | any_privileges(false) { | |
| 2713 | 70122457 | collation.set(DERIVATION_IMPLICIT); | |
| 2714 | 70122373 | } | |
| 2715 | |||
| 2716 | 70121944 | bool Item_field::itemize(Parse_context *pc, Item **res) { | |
| 2717 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 70122189 times.
|
70121944 | if (skip_itemize(res)) return false; |
| 2718 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70122331 times.
|
70122189 | if (super::itemize(pc, res)) return true; |
| 2719 | 70122331 | Query_block *const select = pc->select; | |
| 2720 |
2/2✓ Branch 0 taken 70118888 times.
✓ Branch 1 taken 3443 times.
|
70122331 | if (select->parsing_place != CTX_HAVING) select->select_n_where_fields++; |
| 2721 | 70122331 | return false; | |
| 2722 | } | ||
| 2723 | |||
| 2724 | /** | ||
| 2725 | Used to create a copy (clone) of another Item_field. | ||
| 2726 | Item has same lifetime as the copied item. | ||
| 2727 | |||
| 2728 | @param thd thread handler | ||
| 2729 | @param item Column reference to make a copy from. | ||
| 2730 | */ | ||
| 2731 | |||
| 2732 | 425219 | Item_field::Item_field(THD *thd, Item_field *item) | |
| 2733 | : Item_ident(thd, item), | ||
| 2734 | 425219 | table_ref(item->table_ref), | |
| 2735 | 425219 | field(item->field), | |
| 2736 | 425219 | result_field(item->result_field), | |
| 2737 | 425219 | item_equal(item->item_equal), | |
| 2738 | 425219 | field_index(item->field_index), | |
| 2739 | 425219 | no_constant_propagation(item->no_constant_propagation), | |
| 2740 | 425219 | have_privileges(item->have_privileges), | |
| 2741 | 425219 | any_privileges(item->any_privileges) { | |
| 2742 | 425219 | collation.set(DERIVATION_IMPLICIT); | |
| 2743 |
2/2✓ Branch 0 taken 421075 times.
✓ Branch 1 taken 4144 times.
|
425219 | if (item->m_orig_table_name != nullptr) |
| 2744 | 421075 | m_orig_table_name = item->m_orig_table_name; | |
| 2745 | else | ||
| 2746 | 4144 | m_orig_table_name = nullptr; | |
| 2747 |
1/2✓ Branch 0 taken 425224 times.
✗ Branch 1 not taken.
|
425219 | set_base_item_field(item); |
| 2748 | 425224 | } | |
| 2749 | |||
| 2750 | /** | ||
| 2751 | Create column reference based on a table field. | ||
| 2752 | |||
| 2753 | @param f Pointer to field in a TABLE object | ||
| 2754 | |||
| 2755 | Item is resolved after construction. | ||
| 2756 | Notice that lifetime of object is limited to the lifetime of the | ||
| 2757 | supplied field. | ||
| 2758 | */ | ||
| 2759 | 3028170 | Item_field::Item_field(Field *f) | |
| 2760 | 3028170 | : Item_ident(nullptr, nullptr, *f->table_name, f->field_name), | |
| 2761 | 3028176 | table_ref(nullptr), | |
| 2762 | 3028176 | field(nullptr), | |
| 2763 | 3028176 | item_equal(nullptr), | |
| 2764 | 3028176 | field_index(NO_FIELD_INDEX), | |
| 2765 | 3028176 | have_privileges(0), | |
| 2766 | 3028170 | any_privileges(false) { | |
| 2767 |
2/2✓ Branch 0 taken 121488 times.
✓ Branch 1 taken 2906688 times.
|
3028176 | if (f->table->pos_in_table_list != nullptr) |
| 2768 | 121488 | context = &(f->table->pos_in_table_list->query_block->context); | |
| 2769 | |||
| 2770 |
1/2✓ Branch 0 taken 3028173 times.
✗ Branch 1 not taken.
|
3028176 | set_field(f); |
| 2771 | 3028173 | } | |
| 2772 | |||
| 2773 | /** | ||
| 2774 | Calculate the max column length not taking into account the | ||
| 2775 | limitations over integer types. | ||
| 2776 | |||
| 2777 | When storing data into fields the server currently just ignores the | ||
| 2778 | limits specified on integer types, e.g. 1234 can safely be stored in | ||
| 2779 | an int(2) and will not cause an error. | ||
| 2780 | Thus when creating temporary tables and doing transformations | ||
| 2781 | we must adjust the maximum field length to reflect this fact. | ||
| 2782 | We take the un-restricted maximum length and adjust it similarly to | ||
| 2783 | how the declared length is adjusted wrt unsignedness etc. | ||
| 2784 | TODO: this all needs to go when we disable storing 1234 in int(2). | ||
| 2785 | |||
| 2786 | @param field_par Original field the use to calculate the lengths | ||
| 2787 | @param max_length Item's calculated explicit max length | ||
| 2788 | @return The adjusted max length | ||
| 2789 | */ | ||
| 2790 | |||
| 2791 | 83325955 | inline static uint32 adjust_max_effective_column_length(Field *field_par, | |
| 2792 | uint32 max_length) { | ||
| 2793 | 83325955 | uint32 new_max_length = field_par->max_display_length(); | |
| 2794 |
2/2✓ Branch 0 taken 22209597 times.
✓ Branch 1 taken 61116685 times.
|
83326107 | uint32 sign_length = field_par->is_flag_set(UNSIGNED_FLAG) ? 0 : 1; |
| 2795 | |||
| 2796 |
3/3✓ Branch 0 taken 27306 times.
✓ Branch 1 taken 21391268 times.
✓ Branch 2 taken 61907834 times.
|
83326282 | switch (field_par->type()) { |
| 2797 | 27306 | case MYSQL_TYPE_INT24: | |
| 2798 | /* | ||
| 2799 | Compensate for MAX_MEDIUMINT_WIDTH being 1 too long (8) | ||
| 2800 | compared to the actual number of digits that can fit into | ||
| 2801 | the column. | ||
| 2802 | */ | ||
| 2803 | 27306 | new_max_length += 1; | |
| 2804 | [[fallthrough]]; | ||
| 2805 | 21418574 | case MYSQL_TYPE_LONG: | |
| 2806 | case MYSQL_TYPE_TINY: | ||
| 2807 | case MYSQL_TYPE_SHORT: | ||
| 2808 | |||
| 2809 | /* Take out the sign and add a conditional sign */ | ||
| 2810 | 21418574 | new_max_length = new_max_length - 1 + sign_length; | |
| 2811 | 21418574 | break; | |
| 2812 | |||
| 2813 | /* BINGINT is always 20 no matter the sign */ | ||
| 2814 | 61907834 | case MYSQL_TYPE_LONGLONG: | |
| 2815 | /* make gcc happy */ | ||
| 2816 | default: | ||
| 2817 | 61907834 | break; | |
| 2818 | } | ||
| 2819 | |||
| 2820 | /* Adjust only if the actual precision based one is bigger than specified */ | ||
| 2821 |
2/2✓ Branch 0 taken 505377 times.
✓ Branch 1 taken 82821031 times.
|
83326408 | return new_max_length > max_length ? new_max_length : max_length; |
| 2822 | } | ||
| 2823 | |||
| 2824 | 83326114 | void Item_field::set_field(Field *field_par) { | |
| 2825 | 83326114 | table_ref = field_par->table->pos_in_table_list; | |
| 2826 |
3/4✓ Branch 0 taken 80307177 times.
✓ Branch 1 taken 3018937 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80307177 times.
|
83326114 | assert(table_ref == nullptr || table_ref->table == field_par->table); |
| 2827 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83326476 times.
|
83326114 | assert(field_par->field_index() != NO_FIELD_INDEX); |
| 2828 | 83326476 | field_index = field_par->field_index(); | |
| 2829 | |||
| 2830 | 83326665 | field = result_field = field_par; // for easy coding with fields | |
| 2831 |
6/6✓ Branch 0 taken 54824967 times.
✓ Branch 1 taken 28501568 times.
✓ Branch 2 taken 54795506 times.
✓ Branch 3 taken 29465 times.
✓ Branch 4 taken 2948250 times.
✓ Branch 5 taken 51847259 times.
|
138122174 | set_nullable(field->is_nullable() || field->is_tmp_nullable() || |
| 2832 | 54795506 | field->table->is_nullable()); | |
| 2833 |
2/2✓ Branch 0 taken 80306855 times.
✓ Branch 1 taken 3019196 times.
|
83326051 | if (table_ref != nullptr) { |
| 2834 | 80306855 | table_name = table_ref->alias; | |
| 2835 | 80306855 | m_orig_db_name = table_ref->db; | |
| 2836 | 80306855 | db_name = m_orig_db_name; | |
| 2837 | 80306855 | m_orig_table_name = table_ref->table_name; | |
| 2838 |
2/2✓ Branch 0 taken 469839 times.
✓ Branch 1 taken 79837457 times.
|
80306855 | if (table_ref->is_derived()) { |
| 2839 | // Show underlying field's information | ||
| 2840 | 469839 | m_orig_db_name = field_par->orig_db_name; | |
| 2841 | 469839 | m_orig_table_name = field_par->orig_table_name; | |
| 2842 | } | ||
| 2843 | } else { | ||
| 2844 | 3019196 | m_orig_db_name = field_par->orig_db_name; | |
| 2845 | 3019196 | db_name = m_orig_db_name; | |
| 2846 | 3019196 | m_orig_table_name = field_par->orig_table_name; | |
| 2847 | 3019196 | table_name = m_orig_table_name; | |
| 2848 | } | ||
| 2849 | |||
| 2850 | 83326492 | m_orig_field_name = field_par->field_name; | |
| 2851 | 83325770 | collation.set(field_par->charset(), field_par->derivation(), | |
| 2852 | 83326492 | field_par->repertoire()); | |
| 2853 | 83326255 | set_data_type(field_par->type()); | |
| 2854 | 83325946 | decimals = field->decimals(); | |
| 2855 | 83326206 | unsigned_flag = field_par->is_flag_set(UNSIGNED_FLAG); | |
| 2856 | 83326669 | max_length = char_to_byte_length_safe(field_par->char_length(), | |
| 2857 | 83326006 | collation.collation->mbmaxlen); | |
| 2858 | |||
| 2859 | 83326277 | max_length = adjust_max_effective_column_length(field_par, max_length); | |
| 2860 | |||
| 2861 |
2/2✓ Branch 0 taken 1633883 times.
✓ Branch 1 taken 81692650 times.
|
83326533 | if (field->table->s->tmp_table == SYSTEM_TMP_TABLE) any_privileges = false; |
| 2862 |
2/2✓ Branch 0 taken 82950579 times.
✓ Branch 1 taken 375954 times.
|
83326533 | if (!can_use_prefix_key) |
| 2863 | 82950579 | field->table->covering_keys.subtract(field->part_of_prefixkey); | |
| 2864 | |||
| 2865 | 83325747 | fixed = true; | |
| 2866 | 83325747 | } | |
| 2867 | |||
| 2868 | /** | ||
| 2869 | Reset this item to point to a field from the new temporary table. | ||
| 2870 | This is used when we create a new temporary table for each execution | ||
| 2871 | of prepared statement. | ||
| 2872 | */ | ||
| 2873 | |||
| 2874 | 117 | void Item_field::reset_field(Field *f) { | |
| 2875 | 117 | set_field(f); | |
| 2876 | /* 'name' is pointing at field->field_name of old field */ | ||
| 2877 | 117 | item_name.set(f->field_name); | |
| 2878 | 117 | } | |
| 2879 | |||
| 2880 | 14350 | const char *Item_ident::full_name() const { | |
| 2881 | 14350 | const char *f_name = | |
| 2882 |
1/2✓ Branch 0 taken 14350 times.
✗ Branch 1 not taken.
|
14350 | m_orig_field_name != nullptr ? m_orig_field_name : field_name; |
| 2883 | char *tmp; | ||
| 2884 |
3/4✓ Branch 0 taken 13185 times.
✓ Branch 1 taken 1165 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13185 times.
|
14350 | if (table_name == nullptr || f_name == nullptr) |
| 2885 | return f_name != nullptr | ||
| 2886 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
|
1165 | ? f_name |
| 2887 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
1165 | : item_name.is_set() ? item_name.ptr() : "tmp_field"; |
| 2888 |
4/4✓ Branch 0 taken 13095 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 12977 times.
✓ Branch 3 taken 118 times.
|
13185 | if (db_name && db_name[0]) { |
| 2889 | 12977 | tmp = pointer_cast<char *>( | |
| 2890 | 12977 | (*THR_MALLOC) | |
| 2891 | 12977 | ->Alloc(strlen(db_name) + strlen(table_name) + strlen(f_name) + 3)); | |
| 2892 | 12977 | strxmov(tmp, db_name, ".", table_name, ".", f_name, NullS); | |
| 2893 | } else { | ||
| 2894 |
1/2✓ Branch 0 taken 208 times.
✗ Branch 1 not taken.
|
208 | if (table_name[0]) { |
| 2895 | 208 | tmp = pointer_cast<char *>( | |
| 2896 | 208 | (*THR_MALLOC)->Alloc(strlen(table_name) + strlen(f_name) + 2)); | |
| 2897 | 208 | strxmov(tmp, table_name, ".", f_name, NullS); | |
| 2898 | } else | ||
| 2899 | ✗ | return f_name; | |
| 2900 | } | ||
| 2901 | 13185 | return tmp; | |
| 2902 | } | ||
| 2903 | |||
| 2904 | 5191318 | void Item_ident::print(const THD *thd, String *str, enum_query_type query_type, | |
| 2905 | const char *db_name_arg, | ||
| 2906 | const char *table_name_arg) const { | ||
| 2907 | char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME]; | ||
| 2908 | 5191318 | const char *d_name = db_name_arg; | |
| 2909 | 5191318 | const char *t_name = table_name_arg; | |
| 2910 | 5191318 | const char *f_name = | |
| 2911 |
2/2✓ Branch 0 taken 5190662 times.
✓ Branch 1 taken 656 times.
|
5191318 | m_orig_field_name != nullptr ? m_orig_field_name : field_name; |
| 2912 | |||
| 2913 |
4/4✓ Branch 0 taken 4575099 times.
✓ Branch 1 taken 616219 times.
✓ Branch 2 taken 616220 times.
✓ Branch 3 taken 4575098 times.
|
9766417 | if (lower_case_table_names == 1 || |
| 2914 | // mode '2' does not apply to aliases: | ||
| 2915 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 4575099 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4575099 | (lower_case_table_names == 2 && !alias_name_used())) { |
| 2916 |
4/4✓ Branch 0 taken 615290 times.
✓ Branch 1 taken 930 times.
✓ Branch 2 taken 614368 times.
✓ Branch 3 taken 922 times.
|
616220 | if (table_name_arg && table_name_arg[0]) { |
| 2917 | 614368 | my_stpcpy(t_name_buff, table_name_arg); | |
| 2918 |
1/2✓ Branch 0 taken 614368 times.
✗ Branch 1 not taken.
|
614368 | my_casedn_str(files_charset_info, t_name_buff); |
| 2919 | 614368 | t_name = t_name_buff; | |
| 2920 | } | ||
| 2921 |
4/4✓ Branch 0 taken 615290 times.
✓ Branch 1 taken 930 times.
✓ Branch 2 taken 597945 times.
✓ Branch 3 taken 17345 times.
|
616220 | if (db_name_arg && db_name_arg[0]) { |
| 2922 | 597945 | my_stpcpy(d_name_buff, db_name_arg); | |
| 2923 |
1/2✓ Branch 0 taken 597945 times.
✗ Branch 1 not taken.
|
597945 | my_casedn_str(files_charset_info, d_name_buff); |
| 2924 | 597945 | d_name = d_name_buff; | |
| 2925 | } | ||
| 2926 | } | ||
| 2927 | |||
| 2928 |
5/6✓ Branch 0 taken 5148929 times.
✓ Branch 1 taken 42389 times.
✓ Branch 2 taken 5148929 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 5148927 times.
|
5191318 | if (table_name_arg == nullptr || f_name == nullptr || !f_name[0]) { |
| 2929 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42368 times.
|
42370 | const char *nm = (f_name != nullptr && f_name[0]) |
| 2930 |
2/2✓ Branch 0 taken 42370 times.
✓ Branch 1 taken 21 times.
|
84782 | ? f_name |
| 2931 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
|
23 | : item_name.is_set() ? item_name.ptr() : "tmp_field"; |
| 2932 |
1/2✓ Branch 0 taken 42391 times.
✗ Branch 1 not taken.
|
42391 | append_identifier(thd, str, nm, strlen(nm)); |
| 2933 | 42391 | return; | |
| 2934 | } | ||
| 2935 | |||
| 2936 |
8/8✓ Branch 0 taken 5147869 times.
✓ Branch 1 taken 1058 times.
✓ Branch 2 taken 5147813 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 4995995 times.
✓ Branch 5 taken 151818 times.
✓ Branch 6 taken 2916461 times.
✓ Branch 7 taken 2232466 times.
|
10144922 | if (!(query_type & QT_NO_DB) && db_name_arg && db_name_arg[0] && |
| 2937 |
3/4✓ Branch 0 taken 4995995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2916460 times.
✓ Branch 3 taken 2079535 times.
|
4995995 | !alias_name_used()) { |
| 2938 | 2916461 | const size_t d_name_len = strlen(d_name); | |
| 2939 |
4/4✓ Branch 0 taken 60253 times.
✓ Branch 1 taken 2856208 times.
✓ Branch 2 taken 2866016 times.
✓ Branch 3 taken 50445 times.
|
2976714 | if (!((query_type & QT_NO_DEFAULT_DB) && |
| 2940 |
3/4✓ Branch 0 taken 60253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9808 times.
✓ Branch 3 taken 50445 times.
|
60253 | db_is_default_db(d_name, d_name_len, thd))) { |
| 2941 |
1/2✓ Branch 0 taken 2866016 times.
✗ Branch 1 not taken.
|
2866016 | append_identifier(thd, str, d_name, d_name_len); |
| 2942 |
1/2✓ Branch 0 taken 2866016 times.
✗ Branch 1 not taken.
|
2866016 | str->append('.'); |
| 2943 | } | ||
| 2944 | } | ||
| 2945 |
4/4✓ Branch 0 taken 5147870 times.
✓ Branch 1 taken 1057 times.
✓ Branch 2 taken 5133253 times.
✓ Branch 3 taken 14617 times.
|
5148927 | if (!(query_type & QT_NO_TABLE) && table_name_arg[0]) { |
| 2946 |
1/2✓ Branch 0 taken 5133253 times.
✗ Branch 1 not taken.
|
5133253 | append_identifier(thd, str, t_name, strlen(t_name)); |
| 2947 |
1/2✓ Branch 0 taken 5133253 times.
✗ Branch 1 not taken.
|
5133253 | str->append('.'); |
| 2948 | } | ||
| 2949 |
1/2✓ Branch 0 taken 5148928 times.
✗ Branch 1 not taken.
|
5148927 | append_identifier(thd, str, f_name, strlen(f_name)); |
| 2950 | } | ||
| 2951 | |||
| 2952 | 598 | TYPELIB *Item_field::get_typelib() const { | |
| 2953 | 598 | return down_cast<Field_enum *>(field)->typelib; | |
| 2954 | } | ||
| 2955 | |||
| 2956 | 656424746 | String *Item_field::val_str(String *str) { | |
| 2957 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 656424746 times.
|
656424746 | assert(fixed == 1); |
| 2958 |
2/2✓ Branch 0 taken 29927040 times.
✓ Branch 1 taken 626497886 times.
|
656424746 | if ((null_value = field->is_null())) return nullptr; |
| 2959 | 626497886 | str->set_charset(str_value.charset()); | |
| 2960 | 626497881 | return field->val_str(str, &str_value); | |
| 2961 | } | ||
| 2962 | |||
| 2963 | 865458 | bool Item_field::val_json(Json_wrapper *result) { | |
| 2964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 865458 times.
|
865458 | assert(fixed); |
| 2965 |
3/4✓ Branch 0 taken 1112 times.
✓ Branch 1 taken 864515 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1112 times.
|
865458 | assert(data_type() == MYSQL_TYPE_JSON || returns_array()); |
| 2966 | 865627 | null_value = field->is_null(); | |
| 2967 |
2/2✓ Branch 0 taken 2207 times.
✓ Branch 1 taken 863499 times.
|
865706 | if (null_value) return false; |
| 2968 | 863499 | return down_cast<Field_json *>(field)->val_json(result); | |
| 2969 | } | ||
| 2970 | |||
| 2971 | 7723195 | double Item_field::val_real() { | |
| 2972 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7723195 times.
|
7723195 | assert(fixed == 1); |
| 2973 |
2/2✓ Branch 0 taken 45696 times.
✓ Branch 1 taken 7677504 times.
|
7723195 | if ((null_value = field->is_null())) return 0.0; |
| 2974 | 7677504 | return field->val_real(); | |
| 2975 | } | ||
| 2976 | |||
| 2977 | 381246789 | longlong Item_field::val_int() { | |
| 2978 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 381246789 times.
|
381246789 | assert(fixed == 1); |
| 2979 |
2/2✓ Branch 0 taken 16970584 times.
✓ Branch 1 taken 364276701 times.
|
381246789 | if ((null_value = field->is_null())) return 0; |
| 2980 | 364276701 | return field->val_int(); | |
| 2981 | } | ||
| 2982 | |||
| 2983 | 7603 | longlong Item_field::val_time_temporal() { | |
| 2984 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7603 times.
|
7603 | assert(fixed == 1); |
| 2985 |
2/2✓ Branch 0 taken 200 times.
✓ Branch 1 taken 7403 times.
|
7603 | if ((null_value = field->is_null())) return 0; |
| 2986 | 7403 | return field->val_time_temporal(); | |
| 2987 | } | ||
| 2988 | |||
| 2989 | 85941 | longlong Item_field::val_date_temporal() { | |
| 2990 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85941 times.
|
85941 | assert(fixed == 1); |
| 2991 |
2/2✓ Branch 0 taken 880 times.
✓ Branch 1 taken 85061 times.
|
85941 | if ((null_value = field->is_null())) return 0; |
| 2992 | 85061 | return field->val_date_temporal(); | |
| 2993 | } | ||
| 2994 | |||
| 2995 | 10045 | longlong Item_field::val_time_temporal_at_utc() { | |
| 2996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10045 times.
|
10045 | assert(fixed == 1); |
| 2997 |
2/2✓ Branch 0 taken 155 times.
✓ Branch 1 taken 9890 times.
|
10045 | if ((null_value = field->is_null())) return 0; |
| 2998 | 9890 | return field->val_time_temporal_at_utc(); | |
| 2999 | } | ||
| 3000 | |||
| 3001 | 45583 | longlong Item_field::val_date_temporal_at_utc() { | |
| 3002 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45583 times.
|
45583 | assert(fixed == 1); |
| 3003 |
2/2✓ Branch 0 taken 1733 times.
✓ Branch 1 taken 43850 times.
|
45583 | if ((null_value = field->is_null())) return 0; |
| 3004 | 43850 | return field->val_date_temporal_at_utc(); | |
| 3005 | } | ||
| 3006 | |||
| 3007 | 37001583 | my_decimal *Item_field::val_decimal(my_decimal *decimal_value) { | |
| 3008 | 37001583 | null_value = field->is_null(); | |
| 3009 |
2/2✓ Branch 0 taken 407404 times.
✓ Branch 1 taken 36594179 times.
|
37001583 | if (null_value) return nullptr; |
| 3010 | 36594179 | return field->val_decimal(decimal_value); | |
| 3011 | } | ||
| 3012 | |||
| 3013 | 20651 | bool Item_field::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) { | |
| 3014 |
6/6✓ Branch 0 taken 19452 times.
✓ Branch 1 taken 1199 times.
✓ Branch 2 taken 592 times.
✓ Branch 3 taken 18860 times.
✓ Branch 4 taken 1791 times.
✓ Branch 5 taken 18860 times.
|
20651 | if ((null_value = field->is_null()) || field->get_date(ltime, fuzzydate)) { |
| 3015 | 1791 | memset(ltime, 0, sizeof(*ltime)); | |
| 3016 | 1791 | return true; | |
| 3017 | } | ||
| 3018 | 18860 | return false; | |
| 3019 | } | ||
| 3020 | |||
| 3021 | 3326 | bool Item_field::get_time(MYSQL_TIME *ltime) { | |
| 3022 |
6/6✓ Branch 0 taken 3176 times.
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 145 times.
✓ Branch 3 taken 3031 times.
✓ Branch 4 taken 295 times.
✓ Branch 5 taken 3031 times.
|
3326 | if ((null_value = field->is_null()) || field->get_time(ltime)) { |
| 3023 | 295 | memset(ltime, 0, sizeof(*ltime)); | |
| 3024 | 295 | return true; | |
| 3025 | } | ||
| 3026 | 3031 | return false; | |
| 3027 | } | ||
| 3028 | |||
| 3029 | 2045 | bool Item_field::get_timeval(my_timeval *tm, int *warnings) { | |
| 3030 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 2000 times.
|
2045 | if ((null_value = field->is_null())) return true; |
| 3031 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 1981 times.
|
2000 | if (field->get_timestamp(tm, warnings)) tm->m_tv_sec = tm->m_tv_usec = 0; |
| 3032 | 2000 | return false; | |
| 3033 | } | ||
| 3034 | |||
| 3035 | 13103748 | bool Item_field::eq(const Item *item, bool) const { | |
| 3036 | 13103748 | const Item *real_item = item->real_item(); | |
| 3037 |
2/2✓ Branch 0 taken 3225107 times.
✓ Branch 1 taken 9878643 times.
|
13103743 | if (real_item->type() != FIELD_ITEM) return false; |
| 3038 | |||
| 3039 | 9878643 | const Item_field *item_field = down_cast<const Item_field *>(real_item); | |
| 3040 | |||
| 3041 | /* | ||
| 3042 | If both Item_field objects are properly resolved, return true if they both | ||
| 3043 | refer to the same underlying table field. If one or both fields refer to | ||
| 3044 | temporary table fields derived from some base table field, return true | ||
| 3045 | also if they refer to the same base table field. | ||
| 3046 | The original table's name and original field's name cannot serve here, | ||
| 3047 | consider: SELECT a FROM t1 WHERE b IN (SELECT a FROM t1) | ||
| 3048 | where the semijoin-merged 'a' and the top query's 'a' are both named t1.a | ||
| 3049 | and coexist in the top query. | ||
| 3050 | */ | ||
| 3051 |
4/4✓ Branch 0 taken 9624575 times.
✓ Branch 1 taken 254071 times.
✓ Branch 2 taken 9624365 times.
✓ Branch 3 taken 210 times.
|
9878646 | if (fixed && item_field->fixed) |
| 3052 | 9624365 | return base_item_field()->field == item_field->base_item_field()->field; | |
| 3053 | /* | ||
| 3054 | We may come here when we are trying to find a function in a GROUP BY | ||
| 3055 | clause from the select list. | ||
| 3056 | In this case the '100 % correct' way to do this would be to first | ||
| 3057 | run fix_fields() on the GROUP BY item and then retry this function, but | ||
| 3058 | I think it's better to relax the checking a bit as we will in | ||
| 3059 | most cases do the correct thing by just checking the field name. | ||
| 3060 | (In cases where we would choose wrong we would have to generate a | ||
| 3061 | ER_NON_UNIQ_ERROR). | ||
| 3062 | */ | ||
| 3063 |
2/2✓ Branch 0 taken 145131 times.
✓ Branch 1 taken 109157 times.
|
399412 | return (item_field->item_name.eq_safe(field_name) && |
| 3064 |
4/4✓ Branch 0 taken 144911 times.
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 126214 times.
✓ Branch 3 taken 18697 times.
|
145131 | (!item_field->table_name || !table_name || |
| 3065 |
2/2✓ Branch 0 taken 126212 times.
✓ Branch 1 taken 2 times.
|
126214 | (!my_strcasecmp(table_alias_charset, item_field->table_name, |
| 3066 | 126212 | table_name) && | |
| 3067 |
3/4✓ Branch 0 taken 126212 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53674 times.
✓ Branch 3 taken 72538 times.
|
126212 | (!item_field->db_name || !db_name || |
| 3068 |
2/4✓ Branch 0 taken 53674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53674 times.
✗ Branch 3 not taken.
|
307962 | (item_field->db_name && !strcmp(item_field->db_name, db_name)))))); |
| 3069 | } | ||
| 3070 | |||
| 3071 | 11874153683 | table_map Item_field::used_tables() const { | |
| 3072 |
2/2✓ Branch 0 taken 268784 times.
✓ Branch 1 taken 11873884899 times.
|
11874153683 | if (!table_ref) return 1; // Temporary table; always table 0 |
| 3073 |
2/2✓ Branch 0 taken 332530 times.
✓ Branch 1 taken 11873552369 times.
|
11873884899 | if (table_ref->table->const_table) return 0; // const item |
| 3074 |
2/2✓ Branch 0 taken 11873448325 times.
✓ Branch 1 taken 104044 times.
|
11873552369 | return depended_from ? OUTER_REF_TABLE_BIT : table_ref->map(); |
| 3075 | } | ||
| 3076 | |||
| 3077 | 7153 | bool Item_field::used_tables_for_level(uchar *arg) { | |
| 3078 | 7153 | const TABLE_LIST *tr = field->table->pos_in_table_list; | |
| 3079 | // Used by resolver only, so can never reach a "const" table. | ||
| 3080 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7153 times.
|
7153 | assert(!tr->table->const_table); |
| 3081 | 7153 | Used_tables *const ut = pointer_cast<Used_tables *>(arg); | |
| 3082 | /* | ||
| 3083 | When the qualifying query for the field (table_ref->query_block) is the same | ||
| 3084 | level as the requested level, add the table's map. | ||
| 3085 | When the qualifying query for the field is outer relative to the | ||
| 3086 | requested level, add an outer reference. | ||
| 3087 | */ | ||
| 3088 |
2/2✓ Branch 0 taken 7141 times.
✓ Branch 1 taken 12 times.
|
7153 | if (ut->select == tr->query_block) |
| 3089 | 7141 | ut->used_tables |= tr->map(); | |
| 3090 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | else if (ut->select->nest_level > tr->query_block->nest_level) |
| 3091 | 6 | ut->used_tables |= OUTER_REF_TABLE_BIT; | |
| 3092 | |||
| 3093 | 7153 | return false; | |
| 3094 | } | ||
| 3095 | |||
| 3096 | 37052264 | void Item_ident::fix_after_pullout(Query_block *parent_query_block, | |
| 3097 | Query_block *removed_query_block) { | ||
| 3098 | /* | ||
| 3099 | Some field items may be created for use in execution only, without | ||
| 3100 | a name resolution context. They have already been used in execution, | ||
| 3101 | so no transformation is necessary here. | ||
| 3102 | |||
| 3103 | @todo: Provide strict phase-division in optimizer, to make sure that | ||
| 3104 | execution-only objects do not exist during transformation stage. | ||
| 3105 | Then, this test would be deemed unnecessary. | ||
| 3106 | */ | ||
| 3107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37052264 times.
|
37052264 | if (context == nullptr) { |
| 3108 | ✗ | assert(type() == FIELD_ITEM); | |
| 3109 | ✗ | return; | |
| 3110 | } | ||
| 3111 | |||
| 3112 | // context->query_block should already have been updated. | ||
| 3113 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37052264 times.
|
37052264 | assert(context->query_block != removed_query_block); |
| 3114 | |||
| 3115 |
2/2✓ Branch 0 taken 37041118 times.
✓ Branch 1 taken 11146 times.
|
37052264 | if (context->query_block == parent_query_block) { |
| 3116 |
2/2✓ Branch 0 taken 360 times.
✓ Branch 1 taken 37040758 times.
|
37041118 | if (parent_query_block == depended_from) { |
| 3117 | 360 | depended_from = nullptr; | |
| 3118 | // Update the context of this field to that of the parent query | ||
| 3119 | // block since the resolver place is now lifted from the abandoned | ||
| 3120 | // query block to this one. | ||
| 3121 | 360 | context = &parent_query_block->context; | |
| 3122 | } | ||
| 3123 | } else { | ||
| 3124 | /* | ||
| 3125 | The definition scope of this field item reference is inner to the removed | ||
| 3126 | query_block object. | ||
| 3127 | No new resolution is needed, but we may need to update the dependency. | ||
| 3128 | */ | ||
| 3129 |
2/2✓ Branch 0 taken 1596 times.
✓ Branch 1 taken 9550 times.
|
11146 | if (removed_query_block == depended_from) |
| 3130 | 1596 | depended_from = parent_query_block; | |
| 3131 | } | ||
| 3132 | |||
| 3133 |
2/2✓ Branch 0 taken 1792 times.
✓ Branch 1 taken 37050472 times.
|
37052264 | if (depended_from) { |
| 3134 | /* | ||
| 3135 | Refresh used_tables information for subqueries between the definition | ||
| 3136 | scope and resolution scope of the field item reference. | ||
| 3137 | */ | ||
| 3138 | 1792 | Query_block *child_query_block = context->query_block; | |
| 3139 | |||
| 3140 |
2/2✓ Branch 0 taken 80 times.
✓ Branch 1 taken 1792 times.
|
1872 | while (child_query_block->outer_query_block() != depended_from) { |
| 3141 | /* | ||
| 3142 | The subquery on this level is outer-correlated with respect to the field | ||
| 3143 | */ | ||
| 3144 |
1/2✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
|
80 | child_query_block->master_query_expression()->accumulate_used_tables( |
| 3145 | OUTER_REF_TABLE_BIT); | ||
| 3146 | 80 | child_query_block = child_query_block->outer_query_block(); | |
| 3147 | } | ||
| 3148 | |||
| 3149 | /* | ||
| 3150 | child_query_block is query_block immediately inner to the depended_from | ||
| 3151 | level. Now, locate the subquery predicate that contains this query_block | ||
| 3152 | and update used tables information. | ||
| 3153 | */ | ||
| 3154 | 1792 | Used_tables ut(depended_from); | |
| 3155 |
1/2✓ Branch 0 taken 1792 times.
✗ Branch 1 not taken.
|
1792 | (void)walk(&Item::used_tables_for_level, enum_walk::SUBQUERY_POSTFIX, |
| 3156 | pointer_cast<uchar *>(&ut)); | ||
| 3157 |
1/2✓ Branch 0 taken 1792 times.
✗ Branch 1 not taken.
|
1792 | child_query_block->master_query_expression()->accumulate_used_tables( |
| 3158 | ut.used_tables); | ||
| 3159 | } | ||
| 3160 | } | ||
| 3161 | |||
| 3162 | 63408 | Item *Item_field::get_tmp_table_item(THD *thd) { | |
| 3163 |
1/2✓ Branch 0 taken 63407 times.
✗ Branch 1 not taken.
|
63408 | DBUG_TRACE; |
| 3164 |
2/4✓ Branch 0 taken 63406 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63408 times.
✗ Branch 3 not taken.
|
63407 | Item_field *new_item = new Item_field(thd, this); |
| 3165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63408 times.
|
63408 | if (!new_item) return nullptr; /* purecov: inspected */ |
| 3166 | |||
| 3167 | 63408 | new_item->field = new_item->result_field; | |
| 3168 | 63408 | new_item->table_ref = nullptr; // Internal temporary table has no table_ref | |
| 3169 | |||
| 3170 | 63408 | return new_item; | |
| 3171 | 63408 | } | |
| 3172 | |||
| 3173 | 10031 | longlong Item_field::val_int_endpoint(bool, bool *) { | |
| 3174 | 10031 | longlong res = val_int(); | |
| 3175 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 9911 times.
|
10031 | return null_value ? LLONG_MIN : res; |
| 3176 | } | ||
| 3177 | |||
| 3178 | /** | ||
| 3179 | Init an item from a string we KNOW points to a valid longlong. | ||
| 3180 | str_arg does not necessary has to be a \\0 terminated string. | ||
| 3181 | This is always 'signed'. Unsigned values are created with Item_uint() | ||
| 3182 | */ | ||
| 3183 | 55958 | void Item_int::init(const char *str_arg, uint length) { | |
| 3184 | 55958 | const char *end_ptr = str_arg + length; | |
| 3185 | int error; | ||
| 3186 |
1/2✓ Branch 0 taken 55958 times.
✗ Branch 1 not taken.
|
55958 | value = my_strtoll10(str_arg, &end_ptr, &error); |
| 3187 | 55958 | set_max_size(static_cast<uint>(end_ptr - str_arg)); | |
| 3188 |
1/2✓ Branch 0 taken 55958 times.
✗ Branch 1 not taken.
|
55958 | item_name.copy(str_arg, max_length); |
| 3189 | 55958 | fixed = true; | |
| 3190 | 55958 | } | |
| 3191 | |||
| 3192 | 2854921 | my_decimal *Item_int::val_decimal(my_decimal *decimal_value) { | |
| 3193 | 2854921 | int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_value); | |
| 3194 | 2854921 | return decimal_value; | |
| 3195 | } | ||
| 3196 | |||
| 3197 | 279647 | String *Item_int::val_str(String *str) { | |
| 3198 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279647 times.
|
279647 | assert(fixed == 1); |
| 3200 | 279647 | str->set_int(value, unsigned_flag, collation.collation); | |
| 3201 | 279647 | return str; | |
| 3202 | } | ||
| 3203 | |||
| 3204 | 947595 | void Item_int::print(const THD *, String *str, | |
| 3205 | enum_query_type query_type) const { | ||
| 3206 |
2/2✓ Branch 0 taken 256 times.
✓ Branch 1 taken 947339 times.
|
947595 | if (query_type & QT_NORMALIZED_FORMAT) { |
| 3207 |
1/2✓ Branch 0 taken 256 times.
✗ Branch 1 not taken.
|
256 | str->append("?"); |
| 3208 | 256 | return; | |
| 3209 | } | ||
| 3210 | // my_charset_bin is good enough for numbers | ||
| 3211 | |||
| 3212 | // don't rewrite booleans as ints. see bug#21296173 | ||
| 3213 | 947339 | const Name_string *const name = &item_name; | |
| 3214 |
3/4✓ Branch 0 taken 870867 times.
✓ Branch 1 taken 76472 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 870868 times.
|
947339 | const bool is_literal_false = name->is_set() && name->eq("FALSE"); |
| 3215 |
3/4✓ Branch 0 taken 870868 times.
✓ Branch 1 taken 76472 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 870868 times.
|
947340 | const bool is_literal_true = name->is_set() && name->eq("TRUE"); |
| 3216 |
2/4✓ Branch 0 taken 947340 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 947340 times.
|
947340 | if (is_literal_false || is_literal_true) { |
| 3217 | ✗ | str->append(item_name.ptr(), item_name.length(), str->charset()); | |
| 3218 | } else { | ||
| 3219 |
2/2✓ Branch 0 taken 720 times.
✓ Branch 1 taken 946620 times.
|
947340 | if (unsigned_flag) |
| 3220 | 720 | str->append_ulonglong(value); | |
| 3221 | else | ||
| 3222 | 946620 | str->append_longlong(value); | |
| 3223 | } | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | 12 | String *Item_uint::val_str(String *str) { | |
| 3227 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | assert(fixed == 1); |
| 3229 | 12 | str->set((ulonglong)value, collation.collation); | |
| 3230 | 12 | return str; | |
| 3231 | } | ||
| 3232 | |||
| 3233 | 8911 | void Item_uint::print(const THD *, String *str, | |
| 3234 | enum_query_type query_type) const { | ||
| 3235 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8906 times.
|
8911 | if (query_type & QT_NORMALIZED_FORMAT) { |
| 3236 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | str->append("?"); |
| 3237 | 5 | return; | |
| 3238 | } | ||
| 3239 | 8906 | str->append_ulonglong(value); | |
| 3240 | } | ||
| 3241 | |||
| 3242 | 287335 | Item_decimal::Item_decimal(const POS &pos, const char *str_arg, uint length, | |
| 3243 | 287335 | const CHARSET_INFO *charset) | |
| 3244 | 287335 | : super(pos) { | |
| 3245 |
1/2✓ Branch 0 taken 287335 times.
✗ Branch 1 not taken.
|
287335 | str2my_decimal(E_DEC_FATAL_ERROR, str_arg, length, charset, &decimal_value); |
| 3246 | 287335 | item_name.set(str_arg); | |
| 3247 | 287335 | set_data_type(MYSQL_TYPE_NEWDECIMAL); | |
| 3248 | 287335 | decimals = (uint8)decimal_value.frac; | |
| 3249 | 287335 | fixed = true; | |
| 3250 | 574670 | max_length = my_decimal_precision_to_length_no_truncation( | |
| 3251 | 287335 | decimal_value.intg + decimals, decimals, unsigned_flag); | |
| 3252 | 287335 | } | |
| 3253 | |||
| 3254 | 175 | Item_decimal::Item_decimal(longlong val, bool unsig) { | |
| 3255 |
1/2✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
|
175 | int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value); |
| 3256 | 175 | set_data_type(MYSQL_TYPE_NEWDECIMAL); | |
| 3257 | 175 | decimals = (uint8)decimal_value.frac; | |
| 3258 | 175 | fixed = true; | |
| 3259 | 350 | max_length = my_decimal_precision_to_length_no_truncation( | |
| 3260 | 175 | decimal_value.intg + decimals, decimals, unsigned_flag); | |
| 3261 | 175 | } | |
| 3262 | |||
| 3263 | 3 | Item_decimal::Item_decimal(double val) { | |
| 3264 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value); |
| 3265 | 3 | set_data_type(MYSQL_TYPE_NEWDECIMAL); | |
| 3266 | 3 | decimals = (uint8)decimal_value.frac; | |
| 3267 | 3 | fixed = true; | |
| 3268 | 6 | max_length = my_decimal_precision_to_length_no_truncation( | |
| 3269 | 3 | decimal_value.intg + decimals, decimals, unsigned_flag); | |
| 3270 | 3 | } | |
| 3271 | |||
| 3272 | ✗ | Item_decimal::Item_decimal(const Name_string &name_arg, | |
| 3273 | const my_decimal *val_arg, uint decimal_par, | ||
| 3274 | ✗ | uint length) { | |
| 3275 | ✗ | my_decimal2decimal(val_arg, &decimal_value); | |
| 3276 | ✗ | item_name = name_arg; | |
| 3277 | ✗ | set_data_type(MYSQL_TYPE_NEWDECIMAL); | |
| 3278 | ✗ | decimals = (uint8)decimal_par; | |
| 3279 | ✗ | max_length = length; | |
| 3280 | ✗ | fixed = true; | |
| 3281 | } | ||
| 3282 | |||
| 3283 | 2022 | Item_decimal::Item_decimal(my_decimal *value_par) { | |
| 3284 |
1/2✓ Branch 0 taken 2022 times.
✗ Branch 1 not taken.
|
2022 | my_decimal2decimal(value_par, &decimal_value); |
| 3285 | 2022 | set_data_type(MYSQL_TYPE_NEWDECIMAL); | |
| 3286 | 2022 | decimals = (uint8)decimal_value.frac; | |
| 3287 | 2022 | fixed = true; | |
| 3288 | 4044 | max_length = my_decimal_precision_to_length_no_truncation( | |
| 3289 | 2022 | decimal_value.intg + decimals, decimals, unsigned_flag); | |
| 3290 | 2022 | } | |
| 3291 | |||
| 3292 | 7 | Item_decimal::Item_decimal(const uchar *bin, int precision, int scale) { | |
| 3293 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | binary2my_decimal(E_DEC_FATAL_ERROR, bin, &decimal_value, precision, scale); |
| 3294 | 7 | set_data_type(MYSQL_TYPE_NEWDECIMAL); | |
| 3295 | 7 | decimals = (uint8)decimal_value.frac; | |
| 3296 | 7 | fixed = true; | |
| 3297 | 14 | max_length = my_decimal_precision_to_length_no_truncation(precision, decimals, | |
| 3298 | 7 | unsigned_flag); | |
| 3299 | 7 | } | |
| 3300 | |||
| 3301 | 127 | longlong Item_decimal::val_int() { | |
| 3302 | longlong result; | ||
| 3303 |
1/2✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
|
127 | my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &result); |
| 3304 | 127 | return result; | |
| 3305 | } | ||
| 3306 | |||
| 3307 | 24484 | double Item_decimal::val_real() { | |
| 3308 | double result; | ||
| 3309 |
1/2✓ Branch 0 taken 24483 times.
✗ Branch 1 not taken.
|
24484 | my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result); |
| 3310 | 24483 | return result; | |
| 3311 | } | ||
| 3312 | |||
| 3313 | 217 | String *Item_decimal::val_str(String *result) { | |
| 3314 | 217 | result->set_charset(&my_charset_numeric); | |
| 3315 | 217 | my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, result); | |
| 3316 | 217 | return result; | |
| 3317 | } | ||
| 3318 | |||
| 3319 | 15083 | void Item_decimal::print(const THD *, String *str, | |
| 3320 | enum_query_type query_type) const { | ||
| 3321 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15068 times.
|
15083 | if (query_type & QT_NORMALIZED_FORMAT) { |
| 3322 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | str->append("?"); |
| 3323 | 15 | return; | |
| 3324 | } | ||
| 3325 | 15068 | StringBuffer<MAX_DOUBLE_STR_LENGTH + 1> tmp; // +1 for terminating null | |
| 3326 |
1/2✓ Branch 0 taken 15068 times.
✗ Branch 1 not taken.
|
15068 | my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, &tmp); |
| 3327 |
1/2✓ Branch 0 taken 15068 times.
✗ Branch 1 not taken.
|
15068 | str->append(tmp); |
| 3328 | 15068 | } | |
| 3329 | |||
| 3330 | 1068 | bool Item_decimal::eq(const Item *item, bool) const { | |
| 3331 |
5/6✓ Branch 0 taken 784 times.
✓ Branch 1 taken 284 times.
✓ Branch 2 taken 784 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 784 times.
✓ Branch 5 taken 284 times.
|
1068 | if (type() == item->type() && item->basic_const_item()) { |
| 3332 | /* | ||
| 3333 | We need to cast off const to call val_decimal(). This should | ||
| 3334 | be OK for a basic constant. Additionally, we can pass nullptr as | ||
| 3335 | a true decimal constant will return its internal decimal | ||
| 3336 | storage and ignore the argument. | ||
| 3337 | */ | ||
| 3338 | 784 | Item *arg = const_cast<Item *>(item); | |
| 3339 | 784 | const my_decimal *value = arg->val_decimal(nullptr); | |
| 3340 | 784 | return !my_decimal_cmp(&decimal_value, value); | |
| 3341 | } | ||
| 3342 | 284 | return false; | |
| 3343 | } | ||
| 3344 | |||
| 3345 | 88 | void Item_decimal::set_decimal_value(const my_decimal *value_par) { | |
| 3346 | 88 | my_decimal2decimal(value_par, &decimal_value); | |
| 3347 | 88 | decimals = (uint8)decimal_value.frac; | |
| 3348 | 88 | unsigned_flag = !decimal_value.sign(); | |
| 3349 | 176 | max_length = my_decimal_precision_to_length_no_truncation( | |
| 3350 | 88 | decimal_value.intg + decimals, decimals, unsigned_flag); | |
| 3351 | 88 | } | |
| 3352 | |||
| 3353 | 33 | String *Item_float::val_str(String *str) { | |
| 3354 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
|
33 | assert(fixed == 1); |
| 3356 | 33 | str->set_real(value, decimals, &my_charset_bin); | |
| 3357 | 33 | return str; | |
| 3358 | } | ||
| 3359 | |||
| 3360 | 125 | my_decimal *Item_float::val_decimal(my_decimal *decimal_value) { | |
| 3361 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3362 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
|
125 | assert(fixed == 1); |
| 3363 | 125 | double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_value); | |
| 3364 | 125 | return (decimal_value); | |
| 3365 | } | ||
| 3366 | |||
| 3367 | 477 | bool Item_string::set_str_with_copy(const char *str_arg, uint length_arg, | |
| 3368 | const CHARSET_INFO *from_cs) { | ||
| 3369 | unsigned errors; | ||
| 3370 |
2/4✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 477 times.
|
477 | if (str_value.copy(str_arg, length_arg, from_cs, collation.collation, |
| 3371 | &errors)) { | ||
| 3372 | ✗ | return true; | |
| 3373 | } | ||
| 3374 | |||
| 3375 | 477 | fix_char_length(str_value.length()); | |
| 3376 | 477 | return false; | |
| 3377 | } | ||
| 3378 | |||
| 3379 | /** | ||
| 3380 | @sa enum_query_type. | ||
| 3381 | For us to be able to print a query (in debugging, optimizer trace, EXPLAIN | ||
| 3382 | EXTENDED) without changing the query's result, this function must not | ||
| 3383 | modify the item's content. Not even a @c realloc() of @c str_value is | ||
| 3384 | permitted: | ||
| 3385 | @c Item_func_concat::val_str(), @c Item_func_repeat::val_str(), | ||
| 3386 | @c Item_func_encode::val_str() depend on the allocated length; | ||
| 3387 | a change of this length can influence results of CONCAT(), REPEAT(), | ||
| 3388 | ENCODE()... | ||
| 3389 | */ | ||
| 3390 | 1417231 | void Item_string::print(const THD *, String *str, | |
| 3391 | enum_query_type query_type) const { | ||
| 3392 |
2/2✓ Branch 0 taken 698 times.
✓ Branch 1 taken 1416533 times.
|
1417231 | if (query_type & QT_NORMALIZED_FORMAT) { |
| 3393 |
1/2✓ Branch 0 taken 698 times.
✗ Branch 1 not taken.
|
698 | str->append("?"); |
| 3394 | 698 | return; | |
| 3395 | } | ||
| 3396 | |||
| 3397 | const bool print_introducer = | ||
| 3398 |
2/2✓ Branch 0 taken 1395718 times.
✓ Branch 1 taken 20815 times.
|
2812251 | (query_type & QT_FORCE_INTRODUCERS) || |
| 3399 |
4/4✓ Branch 0 taken 1017262 times.
✓ Branch 1 taken 378456 times.
✓ Branch 2 taken 346 times.
✓ Branch 3 taken 1016916 times.
|
1395718 | (!(query_type & QT_WITHOUT_INTRODUCERS) && is_cs_specified()); |
| 3400 | |||
| 3401 |
2/2✓ Branch 0 taken 21161 times.
✓ Branch 1 taken 1395372 times.
|
1416533 | if (print_introducer) { |
| 3402 | 21161 | str->append('_'); | |
| 3403 |
1/2✓ Branch 0 taken 21161 times.
✗ Branch 1 not taken.
|
21161 | str->append(collation.collation->csname); |
| 3404 | } | ||
| 3405 | |||
| 3406 | 1416533 | str->append('\''); | |
| 3407 | |||
| 3408 |
2/2✓ Branch 0 taken 386484 times.
✓ Branch 1 taken 1030049 times.
|
1416533 | if (query_type & QT_TO_SYSTEM_CHARSET) { |
| 3409 |
2/2✓ Branch 0 taken 165 times.
✓ Branch 1 taken 386319 times.
|
386484 | if (print_introducer) { |
| 3410 | /* | ||
| 3411 | Because we wrote an introducer, we must print str_value in its | ||
| 3412 | charset, and the resulting bytes must not be changed until they | ||
| 3413 | reach the end client. | ||
| 3414 | But the caller is asking for system_charset_info, and may later | ||
| 3415 | convert into character_set_results. That means two conversions: we | ||
| 3416 | must ensure that they don't change our printed bytes. | ||
| 3417 | So we print str_value in the least common denominator of the three | ||
| 3418 | charsets involved: ASCII. Non-ASCII characters are printed as \xFF | ||
| 3419 | sequences (which is ASCII too). This way, our bytes will not be | ||
| 3420 | changed. | ||
| 3421 | */ | ||
| 3422 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | ErrConvString tmp(str_value.ptr(), str_value.length(), &my_charset_bin); |
| 3423 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | str->append(tmp.ptr()); |
| 3424 | } else { | ||
| 3425 | // Convert to system charset. | ||
| 3426 | 386319 | convert_and_print(&str_value, str, system_charset_info); | |
| 3427 | } | ||
| 3428 |
2/2✓ Branch 0 taken 1001963 times.
✓ Branch 1 taken 28086 times.
|
1030049 | } else if (query_type & QT_TO_ARGUMENT_CHARSET) { |
| 3429 |
2/2✓ Branch 0 taken 129 times.
✓ Branch 1 taken 1001834 times.
|
1001963 | if (print_introducer) |
| 3430 | 129 | convert_and_print(&str_value, str, collation.collation); | |
| 3431 | else | ||
| 3432 | /* | ||
| 3433 | Convert the string literals to str->charset(), | ||
| 3434 | which is typically equal to charset_set_client. | ||
| 3435 | */ | ||
| 3436 | 1001834 | convert_and_print(&str_value, str, str->charset()); | |
| 3437 | } else { | ||
| 3438 | // Caller wants a result in the charset of str_value. | ||
| 3439 | 28086 | str_value.print(str); | |
| 3440 | } | ||
| 3441 | |||
| 3442 | 1416533 | str->append('\''); | |
| 3443 | } | ||
| 3444 | |||
| 3445 | 60629 | double double_from_string_with_check(const CHARSET_INFO *cs, const char *cptr, | |
| 3446 | const char *end) { | ||
| 3447 | int error; | ||
| 3448 | double tmp; | ||
| 3449 | |||
| 3450 | 60629 | const char *endptr = end; | |
| 3451 |
1/2✓ Branch 0 taken 60629 times.
✗ Branch 1 not taken.
|
60629 | tmp = my_strntod(cs, cptr, end - cptr, &endptr, &error); |
| 3452 |
9/10✓ Branch 0 taken 60628 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5478 times.
✓ Branch 3 taken 55150 times.
✓ Branch 4 taken 5478 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5476 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 5477 times.
✓ Branch 9 taken 55152 times.
|
60629 | if (error || (end != endptr && !check_if_only_end_space(cs, endptr, end))) { |
| 3453 |
1/2✓ Branch 0 taken 5477 times.
✗ Branch 1 not taken.
|
5477 | ErrConvString err(cptr, end - cptr, cs); |
| 3454 | 5477 | push_warning_printf( | |
| 3455 |
2/4✓ Branch 0 taken 5477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5477 times.
✗ Branch 3 not taken.
|
5477 | current_thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE, |
| 3456 |
2/4✓ Branch 0 taken 5477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5477 times.
✗ Branch 3 not taken.
|
5477 | ER_THD(current_thd, ER_TRUNCATED_WRONG_VALUE), "DOUBLE", err.ptr()); |
| 3457 | } | ||
| 3458 | 60629 | return tmp; | |
| 3459 | } | ||
| 3460 | |||
| 3461 | 21467 | double Item_string::val_real() { | |
| 3462 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21467 times.
|
21467 | assert(fixed == 1); |
| 3463 | 21468 | return double_from_string_with_check(str_value.charset(), str_value.ptr(), | |
| 3464 | 42934 | str_value.ptr() + str_value.length()); | |
| 3465 | } | ||
| 3466 | |||
| 3467 | /** | ||
| 3468 | Converts a string to a longlong integer, with warnings. | ||
| 3469 | |||
| 3470 | @param cs charset of string | ||
| 3471 | @param cptr beginning of string | ||
| 3472 | @param end end of string | ||
| 3473 | @param unsigned_target If 0, caller will use result as a signed integer; | ||
| 3474 | if 1: an unsigned integer; | ||
| 3475 | if -1: caller doesn't tell. This influences warnings. | ||
| 3476 | */ | ||
| 3477 | 29391 | longlong longlong_from_string_with_check(const CHARSET_INFO *cs, | |
| 3478 | const char *cptr, const char *end, | ||
| 3479 | int unsigned_target) { | ||
| 3480 | int err; | ||
| 3481 | longlong tmp; | ||
| 3482 | 29391 | const char *endptr = end; | |
| 3483 | |||
| 3484 |
1/2✓ Branch 0 taken 29391 times.
✗ Branch 1 not taken.
|
29391 | tmp = (*(cs->cset->strtoll10))(cs, cptr, &endptr, &err); |
| 3485 |
4/4✓ Branch 0 taken 29001 times.
✓ Branch 1 taken 390 times.
✓ Branch 2 taken 559 times.
✓ Branch 3 taken 28832 times.
|
58392 | if (err > 0 || // range error, or |
| 3486 | // parse error not due to end spaces: | ||
| 3487 |
5/6✓ Branch 0 taken 173 times.
✓ Branch 1 taken 28828 times.
✓ Branch 2 taken 173 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 169 times.
✓ Branch 5 taken 4 times.
|
29001 | (end != endptr && !check_if_only_end_space(cs, endptr, end))) { |
| 3488 |
1/2✓ Branch 0 taken 559 times.
✗ Branch 1 not taken.
|
559 | ErrConvString errstr(cptr, end - cptr, cs); |
| 3489 | |||
| 3490 | 559 | push_warning_printf( | |
| 3491 |
2/4✓ Branch 0 taken 559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 559 times.
✗ Branch 3 not taken.
|
559 | current_thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE, |
| 3492 |
2/4✓ Branch 0 taken 559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 559 times.
✗ Branch 3 not taken.
|
559 | ER_THD(current_thd, ER_TRUNCATED_WRONG_VALUE), "INTEGER", errstr.ptr()); |
| 3493 | } | ||
| 3494 |
4/4✓ Branch 0 taken 99 times.
✓ Branch 1 taken 29292 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 74 times.
|
29391 | if (err < 0 && // string has a minus sign. |
| 3495 | unsigned_target == 1) // value will be used as unsigned. | ||
| 3496 |
2/4✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
|
25 | push_warning(current_thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR, |
| 3497 | "Cast to unsigned converted negative integer to its " | ||
| 3498 | "positive complement"); | ||
| 3499 |
4/4✓ Branch 0 taken 28902 times.
✓ Branch 1 taken 464 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 28888 times.
|
29366 | else if (err == 0 && // string had no minus sign |
| 3500 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
|
14 | tmp < 0 && // the unsigned value is greater than max signed int |
| 3501 | unsigned_target == 0) // and will be used as signed. | ||
| 3502 | { | ||
| 3503 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | push_warning(current_thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR, |
| 3504 | "Cast to signed converted positive out-of-range integer to " | ||
| 3505 | "its negative complement"); | ||
| 3506 | } | ||
| 3507 | 29391 | return tmp; | |
| 3508 | } | ||
| 3509 | |||
| 3510 | 3575 | longlong Item_string::val_int() { | |
| 3511 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3575 times.
|
3575 | assert(fixed); |
| 3512 | 3575 | return longlong_from_string_with_check(str_value.charset(), str_value.ptr(), | |
| 3513 | 3575 | str_value.ptr() + str_value.length(), | |
| 3514 | 3575 | -1); // ignore sign issues | |
| 3515 | } | ||
| 3516 | |||
| 3517 | 254 | my_decimal *Item_string::val_decimal(my_decimal *decimal_value) { | |
| 3518 | 254 | return val_decimal_from_string(decimal_value); | |
| 3519 | } | ||
| 3520 | |||
| 3521 | 769 | bool Item_null::eq(const Item *item, bool) const { | |
| 3522 | 769 | return item->type() == type(); | |
| 3523 | } | ||
| 3524 | |||
| 3525 | 572 | double Item_null::val_real() { | |
| 3526 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3527 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
|
572 | assert(fixed == 1); |
| 3528 | 572 | null_value = true; | |
| 3529 | 572 | return 0.0; | |
| 3530 | } | ||
| 3531 | 6111692 | longlong Item_null::val_int() { | |
| 3532 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3533 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6111692 times.
|
6111692 | assert(fixed == 1); |
| 3534 | 6111692 | null_value = true; | |
| 3535 | 6111692 | return 0; | |
| 3536 | } | ||
| 3537 | |||
| 3538 | 9556495 | String *Item_null::val_str(String *) { | |
| 3539 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 3540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9556495 times.
|
9556495 | assert(fixed == 1); |
| 3541 | 9556495 | null_value = true; | |
| 3542 | 9556495 | return nullptr; | |
| 3543 | } | ||
| 3544 | |||
| 3545 | 294 | my_decimal *Item_null::val_decimal(my_decimal *) { return nullptr; } | |
| 3546 | |||
| 3547 | ✗ | bool Item_null::val_json(Json_wrapper *) { | |
| 3548 | ✗ | null_value = true; | |
| 3549 | ✗ | return false; | |
| 3550 | } | ||
| 3551 | |||
| 3552 | 32 | Item *Item_null::safe_charset_converter(THD *, const CHARSET_INFO *tocs) { | |
| 3553 | 32 | collation.set(tocs); | |
| 3554 | 32 | return this; | |
| 3555 | } | ||
| 3556 | |||
| 3557 | /*********************** Item_param related ******************************/ | ||
| 3558 | |||
| 3559 | 275249 | Item_param::Item_param(const POS &pos, MEM_ROOT *root, uint pos_in_query_arg) | |
| 3560 |
1/2✓ Branch 0 taken 275249 times.
✗ Branch 1 not taken.
|
275249 | : super(pos), pos_in_query(pos_in_query_arg), m_clones(root) { |
| 3561 | 275249 | item_name.set("?"); | |
| 3562 | // Initial type is "invalid type", type will be assigned from context | ||
| 3563 | 275249 | set_nullable(true); // All parameters are nullable | |
| 3564 | 275249 | } | |
| 3565 | |||
| 3566 | 275229 | bool Item_param::itemize(Parse_context *pc, Item **res) { | |
| 3567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 275229 times.
|
275229 | if (skip_itemize(res)) return false; |
| 3568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 275229 times.
|
275229 | if (super::itemize(pc, res)) return true; |
| 3569 | |||
| 3570 | /* | ||
| 3571 | see commentaries in PTI_limit_option_param_marker::itemize() | ||
| 3572 | */ | ||
| 3573 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 275229 times.
|
275229 | assert(*res == this); |
| 3574 | |||
| 3575 | 275229 | LEX *lex = pc->thd->lex; | |
| 3576 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 275228 times.
|
275229 | if (!lex->parsing_options.allows_variable) { |
| 3577 | 1 | my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); | |
| 3578 | 1 | return true; | |
| 3579 | } | ||
| 3580 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 275220 times.
|
275228 | if (lex->reparse_common_table_expr_at) { |
| 3581 | /* | ||
| 3582 | This parameter is a clone, find the Item_param which corresponds to it | ||
| 3583 | in the original statement - its "master". | ||
| 3584 | Calculate the expected position of this master in the original | ||
| 3585 | statement: | ||
| 3586 | */ | ||
| 3587 | 8 | uint master_pos = pos_in_query + lex->reparse_common_table_expr_at; | |
| 3588 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | List_iterator_fast<Item_param> it(lex->param_list); |
| 3589 | Item_param *master; | ||
| 3590 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | while ((master = it++)) { |
| 3591 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (master_pos == master->pos_in_query) { |
| 3592 | // Register it against its master | ||
| 3593 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | return master->add_clone(this); |
| 3594 | } | ||
| 3595 | } | ||
| 3596 | ✗ | assert(false); /* purecov: inspected */ | |
| 3597 | } | ||
| 3598 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 275182 times.
|
275220 | if (!lex->reparse_derived_table_params_at.empty()) { |
| 3599 | // This parameter is a clone, find the Item_param which corresponds | ||
| 3600 | // to it in the original statement - its "master". | ||
| 3601 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | List_iterator_fast<Item_param> it(lex->param_list); |
| 3602 | Item_param *master; | ||
| 3603 | 38 | auto master_pos = lex->reparse_derived_table_params_at.begin(); | |
| 3604 |
1/2✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
|
98 | while ((master = it++)) { |
| 3605 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 60 times.
|
98 | if (*master_pos == master->pos_in_query) { |
| 3606 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | lex->reparse_derived_table_params_at.erase(master_pos); |
| 3607 | // Register it against its master | ||
| 3608 | 38 | pos_in_query = master->pos_in_query; | |
| 3609 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | return master->add_clone(this); |
| 3610 | } | ||
| 3611 | } | ||
| 3612 | ✗ | assert(false); | |
| 3613 | } | ||
| 3614 | |||
| 3615 | 275182 | return false; | |
| 3616 | } | ||
| 3617 | |||
| 3618 | 143283 | bool Item_param::fix_fields(THD *, Item **) { | |
| 3619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 143283 times.
|
143283 | assert(!fixed); |
| 3620 |
2/2✓ Branch 0 taken 140940 times.
✓ Branch 1 taken 2343 times.
|
143283 | if (param_state() == NO_VALUE) { |
| 3621 | // Parameter has no value, set data type from context | ||
| 3622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 140940 times.
|
140940 | assert(data_type() == MYSQL_TYPE_INVALID); |
| 3623 | 140940 | fixed = true; | |
| 3624 | 140940 | return false; | |
| 3625 | } | ||
| 3626 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2330 times.
|
2343 | if (param_state() == NULL_VALUE) { |
| 3627 | // Parameter data type may be ignored, keep existing type | ||
| 3628 | 13 | fixed = true; | |
| 3629 | 13 | return false; | |
| 3630 | } | ||
| 3631 | // Assign data type from actual data value, when given | ||
| 3632 |
7/8✓ Branch 0 taken 975 times.
✓ Branch 1 taken 695 times.
✓ Branch 2 taken 369 times.
✓ Branch 3 taken 152 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 126 times.
✗ Branch 7 not taken.
|
2330 | switch (data_type_actual()) { |
| 3633 | 975 | case MYSQL_TYPE_LONGLONG: | |
| 3634 | 975 | set_data_type_longlong(); | |
| 3635 | 975 | unsigned_flag = is_unsigned_actual(); | |
| 3636 | 975 | break; | |
| 3637 | 695 | case MYSQL_TYPE_NEWDECIMAL: | |
| 3638 | 695 | set_data_type_decimal(DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE); | |
| 3639 | 695 | break; | |
| 3640 | 369 | case MYSQL_TYPE_DOUBLE: | |
| 3641 | 369 | set_data_type_double(); | |
| 3642 | 369 | break; | |
| 3643 | 152 | case MYSQL_TYPE_VARCHAR: | |
| 3644 | // Set data type string with maximum possible size | ||
| 3645 | // @todo WL#6570 - what about blob values??? | ||
| 3646 | 152 | set_data_type_string(65535U / m_collation_actual->mbmaxlen, | |
| 3647 | m_collation_actual); | ||
| 3648 | 152 | break; | |
| 3649 | 5 | case MYSQL_TYPE_DATE: | |
| 3650 | 5 | set_data_type_date(); | |
| 3651 | 5 | break; | |
| 3652 | 8 | case MYSQL_TYPE_TIME: | |
| 3653 | 8 | set_data_type_time(DATETIME_MAX_DECIMALS); | |
| 3654 | 8 | break; | |
| 3655 | 126 | case MYSQL_TYPE_DATETIME: | |
| 3656 | 126 | set_data_type_datetime(DATETIME_MAX_DECIMALS); | |
| 3657 | 126 | break; | |
| 3658 | ✗ | default: | |
| 3659 | ✗ | assert(false); | |
| 3660 | } | ||
| 3661 | // Do not set result type until having a valid type type (i.e. keep original) | ||
| 3662 |
1/2✓ Branch 0 taken 2330 times.
✗ Branch 1 not taken.
|
2330 | if (data_type() != MYSQL_TYPE_INVALID) |
| 3663 | 2330 | m_result_type = type_to_result(data_type()); | |
| 3664 | |||
| 3665 | 2330 | fixed = true; | |
| 3666 | |||
| 3667 | 2330 | return false; | |
| 3668 | } | ||
| 3669 | |||
| 3670 | 140949 | bool Item_param::propagate_type(THD *, const Type_properties &type) { | |
| 3671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 140949 times.
|
140949 | assert(type.m_type != MYSQL_TYPE_INVALID); |
| 3672 |
13/14✓ Branch 0 taken 4560 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 247 times.
✓ Branch 4 taken 131864 times.
✓ Branch 5 taken 2443 times.
✓ Branch 6 taken 131 times.
✓ Branch 7 taken 176 times.
✓ Branch 8 taken 870 times.
✓ Branch 9 taken 285 times.
✓ Branch 10 taken 138 times.
✓ Branch 11 taken 131 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
|
140949 | switch (type.m_type) { |
| 3673 | 4560 | case MYSQL_TYPE_TINY: | |
| 3674 | case MYSQL_TYPE_SHORT: | ||
| 3675 | case MYSQL_TYPE_INT24: | ||
| 3676 | case MYSQL_TYPE_LONG: | ||
| 3677 | case MYSQL_TYPE_LONGLONG: | ||
| 3678 | 4560 | set_data_type_longlong(); | |
| 3679 | 4560 | unsigned_flag = type.m_unsigned_flag; | |
| 3680 | 4560 | break; | |
| 3681 | 1 | case MYSQL_TYPE_BIT: | |
| 3682 | 1 | set_data_type_bit(); | |
| 3683 | 1 | break; | |
| 3684 | 102 | case MYSQL_TYPE_YEAR: | |
| 3685 | 102 | set_data_type_year(); | |
| 3686 | 102 | break; | |
| 3687 | 247 | case MYSQL_TYPE_NEWDECIMAL: | |
| 3688 | case MYSQL_TYPE_DECIMAL: | ||
| 3689 | 247 | set_data_type_decimal(DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE); | |
| 3690 | 247 | break; | |
| 3691 | 131864 | case MYSQL_TYPE_FLOAT: | |
| 3692 | case MYSQL_TYPE_DOUBLE: | ||
| 3693 | 131864 | set_data_type_double(); | |
| 3694 | 131864 | break; | |
| 3695 | 2443 | case MYSQL_TYPE_VARCHAR: | |
| 3696 | case MYSQL_TYPE_VAR_STRING: | ||
| 3697 | case MYSQL_TYPE_STRING: | ||
| 3698 | case MYSQL_TYPE_ENUM: | ||
| 3699 | case MYSQL_TYPE_SET: | ||
| 3700 | // Parameter type is VARCHAR of largest possible size | ||
| 3701 | 2443 | set_data_type_string(65535U / type.m_collation.collation->mbmaxlen, | |
| 3702 | 2443 | type.m_collation); | |
| 3703 | 2443 | break; | |
| 3704 | 131 | case MYSQL_TYPE_GEOMETRY: | |
| 3705 | 131 | set_data_type_geometry(); | |
| 3706 | 131 | break; | |
| 3707 | 176 | case MYSQL_TYPE_JSON: | |
| 3708 | 176 | set_data_type_json(); | |
| 3709 | 176 | break; | |
| 3710 | 870 | case MYSQL_TYPE_TINY_BLOB: | |
| 3711 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 3712 | case MYSQL_TYPE_LONG_BLOB: | ||
| 3713 | case MYSQL_TYPE_BLOB: | ||
| 3714 | // Parameter type is BLOB of largest possible size | ||
| 3715 | 870 | set_data_type_string(Field::MAX_LONG_BLOB_WIDTH, type.m_collation); | |
| 3716 | 870 | break; | |
| 3717 | 285 | case MYSQL_TYPE_DATETIME: | |
| 3718 | case MYSQL_TYPE_DATETIME2: | ||
| 3719 | case MYSQL_TYPE_TIMESTAMP: | ||
| 3720 | case MYSQL_TYPE_TIMESTAMP2: | ||
| 3721 | 285 | set_data_type_datetime(6); | |
| 3722 | 285 | break; | |
| 3723 | 138 | case MYSQL_TYPE_DATE: | |
| 3724 | case MYSQL_TYPE_NEWDATE: | ||
| 3725 | 138 | set_data_type_date(); | |
| 3726 | 138 | break; | |
| 3727 | 131 | case MYSQL_TYPE_TIME: | |
| 3728 | case MYSQL_TYPE_TIME2: | ||
| 3729 | 131 | set_data_type_time(6); | |
| 3730 | 131 | break; | |
| 3731 | 1 | case MYSQL_TYPE_NULL: | |
| 3732 | 1 | set_data_type_string(65535U / type.m_collation.collation->mbmaxlen, | |
| 3733 | 1 | type.m_collation); | |
| 3734 | 1 | break; | |
| 3735 | ✗ | default: | |
| 3736 | ✗ | assert(false); | |
| 3737 | } | ||
| 3738 | |||
| 3739 | 140949 | m_result_type = type_to_result(data_type()); | |
| 3740 | |||
| 3741 | 140949 | return false; | |
| 3742 | } | ||
| 3743 | |||
| 3744 | 435302 | void Item_param::sync_clones() { | |
| 3745 |
2/2✓ Branch 0 taken 92 times.
✓ Branch 1 taken 435297 times.
|
435393 | for (auto c : m_clones) { |
| 3746 | // Scalar-type members: | ||
| 3747 | 92 | c->set_nullable(is_nullable()); | |
| 3748 | 92 | c->null_value = null_value; | |
| 3749 | 92 | c->max_length = max_length; | |
| 3750 | 92 | c->decimals = decimals; | |
| 3751 | 92 | c->unsigned_flag = unsigned_flag; | |
| 3752 | 92 | c->m_param_state = m_param_state; | |
| 3753 | 92 | c->m_result_type = m_result_type; | |
| 3754 | 92 | c->value = value; | |
| 3755 | 92 | c->m_data_type_source = m_data_type_source; | |
| 3756 | 92 | c->m_data_type_actual = m_data_type_actual; | |
| 3757 | 92 | c->m_unsigned_actual = m_unsigned_actual; | |
| 3758 | 92 | c->m_collation_source = m_collation_source; | |
| 3759 | 92 | c->m_collation_actual = m_collation_actual; | |
| 3760 | // Class-type members: | ||
| 3761 | 92 | c->decimal_value = decimal_value; | |
| 3762 | /* | ||
| 3763 | Note that String's assignment op properly sets m_is_alloced to 'false', | ||
| 3764 | which is correct here: c->str_value doesn't own anything. | ||
| 3765 | */ | ||
| 3766 | 92 | c->str_value = str_value; | |
| 3767 | 92 | c->str_value_ptr = str_value_ptr; | |
| 3768 | 91 | c->collation = collation; | |
| 3769 | } | ||
| 3770 | 435297 | } | |
| 3771 | |||
| 3772 | 1126 | void Item_param::set_null() { | |
| 3773 |
1/2✓ Branch 0 taken 1126 times.
✗ Branch 1 not taken.
|
1126 | DBUG_TRACE; |
| 3774 | |||
| 3775 | 1126 | null_value = true; | |
| 3776 | |||
| 3777 | 1126 | m_data_type_actual = MYSQL_TYPE_NULL; | |
| 3778 | 1126 | m_param_state = NULL_VALUE; | |
| 3779 | 1126 | } | |
| 3780 | |||
| 3781 | 8823 | void Item_param::set_int(longlong i) { | |
| 3782 |
1/2✓ Branch 0 taken 8822 times.
✗ Branch 1 not taken.
|
8823 | DBUG_TRACE; |
| 3783 | 8822 | value.integer = i; | |
| 3784 | 8822 | m_data_type_actual = MYSQL_TYPE_LONGLONG; | |
| 3785 | 8822 | m_unsigned_actual = false; | |
| 3786 | 8822 | m_param_state = INT_VALUE; | |
| 3787 | 8822 | } | |
| 3788 | |||
| 3789 | 105 | void Item_param::set_int(ulonglong i) { | |
| 3790 |
1/2✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
|
105 | DBUG_TRACE; |
| 3791 | 105 | value.integer = i; | |
| 3792 | 105 | m_data_type_actual = MYSQL_TYPE_LONGLONG; | |
| 3793 | 105 | m_unsigned_actual = true; | |
| 3794 | 105 | m_param_state = INT_VALUE; | |
| 3795 | 105 | } | |
| 3796 | |||
| 3797 | 131964 | void Item_param::set_double(double d) { | |
| 3798 |
1/2✓ Branch 0 taken 131964 times.
✗ Branch 1 not taken.
|
131964 | DBUG_TRACE; |
| 3799 | 131964 | value.real = d; | |
| 3800 | 131964 | m_data_type_actual = MYSQL_TYPE_DOUBLE; | |
| 3801 | 131964 | m_param_state = REAL_VALUE; | |
| 3802 | 131964 | } | |
| 3803 | |||
| 3804 | /** | ||
| 3805 | Set decimal parameter value from string. | ||
| 3806 | |||
| 3807 | @param str character string | ||
| 3808 | @param length string length | ||
| 3809 | |||
| 3810 | @note | ||
| 3811 | As we use character strings to send decimal values in | ||
| 3812 | binary protocol, we use str2my_decimal to convert it to | ||
| 3813 | internal decimal value. | ||
| 3814 | */ | ||
| 3815 | |||
| 3816 | 14 | void Item_param::set_decimal(const char *str, ulong length) { | |
| 3817 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | DBUG_TRACE; |
| 3818 | |||
| 3819 | 14 | const char *end = str + length; | |
| 3820 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end); |
| 3821 | 14 | m_data_type_actual = MYSQL_TYPE_NEWDECIMAL; | |
| 3822 | 14 | m_param_state = DECIMAL_VALUE; | |
| 3823 | 14 | } | |
| 3824 | |||
| 3825 | 20 | void Item_param::set_decimal(const my_decimal *dv) { | |
| 3826 | 20 | m_param_state = DECIMAL_VALUE; | |
| 3827 | 20 | m_data_type_actual = MYSQL_TYPE_NEWDECIMAL; | |
| 3828 | |||
| 3829 | 20 | my_decimal2decimal(dv, &decimal_value); | |
| 3830 | 20 | } | |
| 3831 | |||
| 3832 | /** | ||
| 3833 | Set parameter value from MYSQL_TIME value. | ||
| 3834 | |||
| 3835 | @param tm datetime value to set (time_type is ignored) | ||
| 3836 | @param time_type type of datetime value | ||
| 3837 | |||
| 3838 | @note | ||
| 3839 | If we value to be stored is not normalized, zero value will be stored | ||
| 3840 | instead and proper warning will be produced. This function relies on | ||
| 3841 | the fact that even wrong value sent over binary protocol fits into | ||
| 3842 | MAX_DATE_STRING_REP_LENGTH buffer. | ||
| 3843 | */ | ||
| 3844 | 221 | void Item_param::set_time(MYSQL_TIME *tm, enum_mysql_timestamp_type time_type) { | |
| 3845 |
1/2✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
|
221 | DBUG_TRACE; |
| 3846 | |||
| 3847 |
7/8✓ Branch 0 taken 166 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 124 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 122 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
221 | assert(time_type == MYSQL_TIMESTAMP_DATE || |
| 3848 | time_type == MYSQL_TIMESTAMP_TIME || | ||
| 3849 | time_type == MYSQL_TIMESTAMP_DATETIME || | ||
| 3850 | time_type == MYSQL_TIMESTAMP_DATETIME_TZ); | ||
| 3851 | |||
| 3852 | 221 | value.time = *tm; | |
| 3853 | 221 | value.time.time_type = time_type; | |
| 3854 |
2/2✓ Branch 0 taken 82 times.
✓ Branch 1 taken 139 times.
|
221 | decimals = tm->second_part ? DATETIME_MAX_DECIMALS : 0; |
| 3855 | |||
| 3856 |
3/4✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 209 times.
|
221 | if (check_datetime_range(value.time)) { |
| 3857 | /* | ||
| 3858 | TODO : Add error handling for Item_param::set_* functions. | ||
| 3859 | make_truncated_value_warning() can return error in STRICT mode. | ||
| 3860 | */ | ||
| 3861 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | (void)make_truncated_value_warning(current_thd, Sql_condition::SL_WARNING, |
| 3862 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | ErrConvString(&value.time, decimals), |
| 3863 | time_type, NullS); | ||
| 3864 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR); |
| 3865 | } | ||
| 3866 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 166 times.
|
221 | if (time_type == MYSQL_TIMESTAMP_DATE) |
| 3867 | 55 | m_data_type_actual = MYSQL_TYPE_DATE; | |
| 3868 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 124 times.
|
166 | else if (time_type == MYSQL_TIMESTAMP_TIME) |
| 3869 | 42 | m_data_type_actual = MYSQL_TYPE_TIME; | |
| 3870 | else | ||
| 3871 | 124 | m_data_type_actual = MYSQL_TYPE_DATETIME; | |
| 3872 | |||
| 3873 | 221 | m_param_state = TIME_VALUE; | |
| 3874 | 221 | } | |
| 3875 | |||
| 3876 | 6395 | bool Item_param::set_str(const char *str, size_t length) { | |
| 3877 |
1/2✓ Branch 0 taken 6396 times.
✗ Branch 1 not taken.
|
6395 | DBUG_TRACE; |
| 3878 | /* | ||
| 3879 | Assign string with no conversion: data is converted only after it's | ||
| 3880 | been written to the binary log. | ||
| 3881 | */ | ||
| 3882 | uint dummy_errors; | ||
| 3883 |
2/4✓ Branch 0 taken 6395 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6395 times.
|
6396 | if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin, |
| 3884 | &dummy_errors)) | ||
| 3885 | ✗ | return true; | |
| 3886 | 6395 | m_data_type_actual = MYSQL_TYPE_VARCHAR; | |
| 3887 | /* | ||
| 3888 | Generally, the character set of the string stored in the parameter object | ||
| 3889 | is the resolved character set of the parameter, except: | ||
| 3890 | - when the resolved character set is a binary string, ensure the string | ||
| 3891 | is in the connection character set. | ||
| 3892 | - when the source string is a binary string, keep it as-is and perform | ||
| 3893 | no conversion. | ||
| 3894 | */ | ||
| 3895 |
2/2✓ Branch 0 taken 5903 times.
✓ Branch 1 taken 493 times.
|
12298 | set_collation_actual(collation_source() == &my_charset_bin |
| 3896 | ? &my_charset_bin | ||
| 3897 | 5903 | : collation.collation != &my_charset_bin | |
| 3898 |
2/2✓ Branch 0 taken 5749 times.
✓ Branch 1 taken 154 times.
|
5903 | ? collation.collation |
| 3899 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | : current_thd->variables.collation_connection); |
| 3900 | |||
| 3901 | 6396 | m_param_state = STRING_VALUE; | |
| 3902 | 6396 | return false; | |
| 3903 | 6396 | } | |
| 3904 | |||
| 3905 | 596 | bool Item_param::set_longdata(const char *str, ulong length) { | |
| 3906 |
1/2✓ Branch 0 taken 596 times.
✗ Branch 1 not taken.
|
596 | DBUG_TRACE; |
| 3907 | |||
| 3908 | /* | ||
| 3909 | If client character set is multibyte, end of long data packet | ||
| 3910 | may hit at the middle of a multibyte character. Additionally, | ||
| 3911 | if binary log is open we must write long data value to the | ||
| 3912 | binary log in character set of client. This is why we can't | ||
| 3913 | convert long data to connection character set as it comes | ||
| 3914 | (here), and first have to concatenate all pieces together, | ||
| 3915 | write query to the binary log and only then perform conversion. | ||
| 3916 | */ | ||
| 3917 |
3/4✓ Branch 0 taken 596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 592 times.
|
596 | if (str_value.length() + length > current_thd->variables.max_allowed_packet) { |
| 3918 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | my_message(ER_UNKNOWN_ERROR, |
| 3919 | "Parameter of prepared statement which is set through " | ||
| 3920 | "mysql_send_long_data() is longer than " | ||
| 3921 | "'max_allowed_packet' bytes", | ||
| 3922 | MYF(0)); | ||
| 3923 | 4 | return true; | |
| 3924 | } | ||
| 3925 | |||
| 3926 |
2/4✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 592 times.
|
592 | if (str_value.append(str, length, &my_charset_bin)) return true; |
| 3927 | |||
| 3928 | /* | ||
| 3929 | Currently, both source type and actual type is MYSQL_TYPE_INVALID. | ||
| 3930 | They will be set to proper values by Prepared_statement::insert_params(). | ||
| 3931 | */ | ||
| 3932 | 592 | m_param_state = LONG_DATA_VALUE; | |
| 3933 | |||
| 3934 | 592 | return false; | |
| 3935 | 596 | } | |
| 3936 | |||
| 3937 | /** | ||
| 3938 | Set parameter value from user variable value. | ||
| 3939 | |||
| 3940 | @param thd Current thread | ||
| 3941 | @param entry User variable structure (NULL means use NULL value) | ||
| 3942 | |||
| 3943 | @returns false if success, true if error | ||
| 3944 | */ | ||
| 3945 | |||
| 3946 | 14507 | bool Item_param::set_from_user_var(THD *thd [[maybe_unused]], | |
| 3947 | const user_var_entry *entry) { | ||
| 3948 |
1/2✓ Branch 0 taken 14508 times.
✗ Branch 1 not taken.
|
14507 | DBUG_TRACE; |
| 3949 |
6/6✓ Branch 0 taken 14469 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 13459 times.
✓ Branch 3 taken 1010 times.
✓ Branch 4 taken 13459 times.
✓ Branch 5 taken 1049 times.
|
14508 | if (entry && entry->ptr()) { |
| 3950 | // An existing user variable that is not NULL | ||
| 3951 | |||
| 3952 | // Pinning of data types only implemented for integers | ||
| 3953 |
3/4✓ Branch 0 taken 51 times.
✓ Branch 1 taken 13408 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
|
13459 | assert(!is_type_pinned() || result_type() == INT_RESULT); |
| 3954 |
6/6✓ Branch 0 taken 51 times.
✓ Branch 1 taken 13408 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 13454 times.
|
13459 | if (is_type_pinned() && entry->type() != INT_RESULT) { |
| 3955 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); |
| 3956 | 5 | return true; | |
| 3957 | } | ||
| 3958 |
5/5✓ Branch 0 taken 651 times.
✓ Branch 1 taken 5802 times.
✓ Branch 2 taken 5727 times.
✓ Branch 3 taken 1272 times.
✓ Branch 4 taken 2 times.
|
13454 | switch (entry->type()) { |
| 3959 | 651 | case REAL_RESULT: | |
| 3960 |
1/2✓ Branch 0 taken 651 times.
✗ Branch 1 not taken.
|
651 | set_double(*pointer_cast<const double *>(entry->ptr())); |
| 3961 | 651 | break; | |
| 3962 | 5802 | case INT_RESULT: | |
| 3963 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 5736 times.
|
5802 | if (entry->unsigned_flag) { |
| 3964 | 66 | ulonglong val = *pointer_cast<const ulonglong *>(entry->ptr()); | |
| 3965 |
4/8✓ Branch 0 taken 5 times.
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 66 times.
|
66 | if (is_type_pinned() && !unsigned_flag && val > INT_MAX64) { |
| 3966 | ✗ | my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "signed integer", "EXECUTE"); | |
| 3967 | ✗ | return true; | |
| 3968 | } | ||
| 3969 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | set_int(val); |
| 3970 | } else { | ||
| 3971 | 5736 | longlong val = *pointer_cast<const longlong *>(entry->ptr()); | |
| 3972 |
8/8✓ Branch 0 taken 41 times.
✓ Branch 1 taken 5695 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 33 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 5733 times.
|
5736 | if (is_type_pinned() && unsigned_flag && val < 0) { |
| 3973 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "unsigned integer", |
| 3974 | "EXECUTE"); | ||
| 3975 | 3 | return true; | |
| 3976 | } | ||
| 3977 |
1/2✓ Branch 0 taken 5734 times.
✗ Branch 1 not taken.
|
5733 | set_int(val); |
| 3978 | } | ||
| 3979 | 5800 | break; | |
| 3980 | 5727 | case STRING_RESULT: | |
| 3981 |
2/4✓ Branch 0 taken 5728 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5728 times.
|
5727 | if (set_str(entry->ptr(), entry->length())) return true; |
| 3982 | 5728 | break; | |
| 3983 | 1272 | case DECIMAL_RESULT: { | |
| 3984 | 1272 | const my_decimal *ent_value = (const my_decimal *)entry->ptr(); | |
| 3985 |
1/2✓ Branch 0 taken 1272 times.
✗ Branch 1 not taken.
|
1272 | my_decimal2decimal(ent_value, &decimal_value); |
| 3986 | 1272 | m_data_type_actual = MYSQL_TYPE_NEWDECIMAL; | |
| 3987 | 1272 | m_param_state = DECIMAL_VALUE; | |
| 3988 | 1272 | break; | |
| 3989 | } | ||
| 3990 | 2 | default: | |
| 3991 | 2 | assert(0); | |
| 3992 | set_null(); | ||
| 3993 | } | ||
| 3994 | } else { | ||
| 3995 |
1/2✓ Branch 0 taken 1049 times.
✗ Branch 1 not taken.
|
1049 | set_null(); |
| 3996 | } | ||
| 3997 | 14500 | return false; | |
| 3998 | 14508 | } | |
| 3999 | |||
| 4000 | /** | ||
| 4001 | Resets parameter after execution. | ||
| 4002 | |||
| 4003 | @note | ||
| 4004 | We clear null_value here instead of setting it in set_* methods, | ||
| 4005 | because we want more easily handle case for long data. | ||
| 4006 | */ | ||
| 4007 | |||
| 4008 | 280852 | void Item_param::reset() { | |
| 4009 |
1/2✓ Branch 0 taken 280858 times.
✗ Branch 1 not taken.
|
280852 | DBUG_TRACE; |
| 4010 | /* Shrink string buffer if it's bigger than max possible CHAR column */ | ||
| 4011 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 280839 times.
|
280858 | if (str_value.alloced_length() > MAX_CHAR_WIDTH) |
| 4012 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | str_value.mem_free(); |
| 4013 | else | ||
| 4014 | 280839 | str_value.length(0); | |
| 4015 | 280860 | str_value_ptr.length(0); | |
| 4016 | 280859 | m_param_state = NO_VALUE; | |
| 4017 | 280859 | m_data_type_actual = MYSQL_TYPE_INVALID; | |
| 4018 | 280859 | null_value = false; | |
| 4019 | 280859 | } | |
| 4020 | |||
| 4021 | 144024 | type_conversion_status Item_param::save_in_field_inner(Field *field, | |
| 4022 | bool no_conversions) { | ||
| 4023 |
2/2✓ Branch 0 taken 881 times.
✓ Branch 1 taken 143145 times.
|
144024 | if (param_state() == NULL_VALUE) { |
| 4024 | 881 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 4025 | } | ||
| 4026 | 143145 | field->set_notnull(); | |
| 4027 | |||
| 4028 |
5/6✓ Branch 0 taken 6829 times.
✓ Branch 1 taken 131949 times.
✓ Branch 2 taken 392 times.
✓ Branch 3 taken 311 times.
✓ Branch 4 taken 3664 times.
✗ Branch 5 not taken.
|
143145 | switch (data_type_actual()) { |
| 4029 | 6829 | case MYSQL_TYPE_LONGLONG: | |
| 4030 | 6829 | return field->store(value.integer, is_unsigned_actual()); | |
| 4031 | 131949 | case MYSQL_TYPE_DOUBLE: | |
| 4032 | 131949 | return field->store(value.real); | |
| 4033 | 392 | case MYSQL_TYPE_NEWDECIMAL: | |
| 4034 | 392 | return field->store_decimal(&decimal_value); | |
| 4035 | 311 | case MYSQL_TYPE_DATE: | |
| 4036 | case MYSQL_TYPE_TIME: | ||
| 4037 | case MYSQL_TYPE_DATETIME: | ||
| 4038 | 311 | field->store_time(&value.time); | |
| 4039 | 311 | return TYPE_OK; | |
| 4040 | 3664 | case MYSQL_TYPE_VARCHAR: | |
| 4041 | 3664 | return field->store(str_value.ptr(), str_value.length(), | |
| 4042 | 3663 | str_value.charset()); | |
| 4043 | ✗ | default: | |
| 4044 | ✗ | assert(0); | |
| 4045 | } | ||
| 4046 | return TYPE_ERR_BAD_VALUE; | ||
| 4047 | } | ||
| 4048 | |||
| 4049 | 50 | bool Item_param::get_time(MYSQL_TIME *res) { | |
| 4050 |
5/5✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 11 times.
|
50 | switch (data_type_actual()) { |
| 4051 | 36 | case MYSQL_TYPE_TIME: | |
| 4052 | case MYSQL_TYPE_DATE: | ||
| 4053 | case MYSQL_TYPE_DATETIME: | ||
| 4054 | 36 | *res = value.time; | |
| 4055 | 36 | return false; | |
| 4056 | 1 | case MYSQL_TYPE_LONGLONG: | |
| 4057 | 1 | return get_time_from_int(res); | |
| 4058 | 1 | case MYSQL_TYPE_DOUBLE: | |
| 4059 | 1 | return get_time_from_real(res); | |
| 4060 | 1 | case MYSQL_TYPE_NEWDECIMAL: | |
| 4061 | 1 | return get_time_from_decimal(res); | |
| 4062 | 11 | default: | |
| 4063 | 11 | return get_time_from_string(res); | |
| 4064 | } | ||
| 4065 | } | ||
| 4066 | |||
| 4067 | 106 | bool Item_param::get_date(MYSQL_TIME *res, my_time_flags_t fuzzydate) { | |
| 4068 |
3/5✓ Branch 0 taken 77 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
|
106 | switch (data_type_actual()) { |
| 4069 | 77 | case MYSQL_TYPE_TIME: | |
| 4070 | case MYSQL_TYPE_DATE: | ||
| 4071 | case MYSQL_TYPE_DATETIME: | ||
| 4072 | 77 | *res = value.time; | |
| 4073 | 77 | return false; | |
| 4074 | 2 | case MYSQL_TYPE_LONGLONG: | |
| 4075 | 2 | return get_date_from_int(res, fuzzydate); | |
| 4076 | ✗ | case MYSQL_TYPE_DOUBLE: | |
| 4077 | ✗ | return get_date_from_real(res, fuzzydate); | |
| 4078 | ✗ | case MYSQL_TYPE_NEWDECIMAL: | |
| 4079 | ✗ | return get_date_from_decimal(res, fuzzydate); | |
| 4080 | 27 | default: | |
| 4081 | 27 | return get_date_from_string(res, fuzzydate); | |
| 4082 | } | ||
| 4083 | } | ||
| 4084 | |||
| 4085 | 1304 | double Item_param::val_real() { | |
| 4086 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1304 times.
|
1304 | assert(data_type() != MYSQL_TYPE_INVALID); |
| 4087 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1304 times.
|
1304 | assert(param_state() != NO_VALUE); |
| 4088 | |||
| 4089 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1288 times.
|
1304 | if (param_state() == NULL_VALUE) { |
| 4090 | 16 | return 0.0; | |
| 4091 | } | ||
| 4092 |
5/6✓ Branch 0 taken 598 times.
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 377 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
1288 | switch (data_type_actual()) { |
| 4093 | 598 | case MYSQL_TYPE_DOUBLE: | |
| 4094 | 598 | return value.real; | |
| 4095 | 300 | case MYSQL_TYPE_LONGLONG: | |
| 4096 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
|
300 | if (is_unsigned_actual()) |
| 4097 | ✗ | return static_cast<double>(static_cast<ulonglong>(value.integer)); | |
| 4098 | else | ||
| 4099 | 300 | return static_cast<double>(value.integer); | |
| 4100 | 377 | case MYSQL_TYPE_NEWDECIMAL: { | |
| 4101 | double result; | ||
| 4102 |
1/2✓ Branch 0 taken 377 times.
✗ Branch 1 not taken.
|
377 | my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result); |
| 4103 | 377 | return result; | |
| 4104 | } | ||
| 4105 | 10 | case MYSQL_TYPE_VARCHAR: { | |
| 4106 | 10 | return double_from_string_with_check( | |
| 4107 | 10 | str_value.charset(), str_value.ptr(), | |
| 4108 | 20 | str_value.ptr() + str_value.length()); | |
| 4109 | } | ||
| 4110 | 3 | case MYSQL_TYPE_DATE: | |
| 4111 | case MYSQL_TYPE_TIME: | ||
| 4112 | case MYSQL_TYPE_DATETIME: | ||
| 4113 | /* | ||
| 4114 | This works for example when user says SELECT ?+0.0 and supplies | ||
| 4115 | time value for the placeholder. | ||
| 4116 | */ | ||
| 4117 | 3 | return TIME_to_double(value.time); | |
| 4118 | ✗ | default: | |
| 4119 | ✗ | assert(0); | |
| 4120 | } | ||
| 4121 | return 0.0; | ||
| 4122 | } | ||
| 4123 | |||
| 4124 | 13875 | longlong Item_param::val_int() { | |
| 4125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13878 times.
|
13875 | assert(data_type() != MYSQL_TYPE_INVALID); |
| 4126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13878 times.
|
13878 | assert(param_state() != NO_VALUE); |
| 4127 | |||
| 4128 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 13743 times.
|
13878 | if (param_state() == NULL_VALUE) { |
| 4129 | 135 | return 0; | |
| 4130 | } | ||
| 4131 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 13650 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
13743 | switch (data_type_actual()) { |
| 4132 | ✗ | case MYSQL_TYPE_DOUBLE: | |
| 4133 | ✗ | return static_cast<longlong>(rint(value.real)); | |
| 4134 | 13650 | case MYSQL_TYPE_LONGLONG: | |
| 4135 | 13650 | return value.integer; | |
| 4136 | 4 | case MYSQL_TYPE_NEWDECIMAL: { | |
| 4137 | longlong i; | ||
| 4138 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &i); |
| 4139 | 4 | return i; | |
| 4140 | } | ||
| 4141 | 86 | case MYSQL_TYPE_VARCHAR: { | |
| 4142 | 86 | return longlong_from_string_with_check( | |
| 4143 | 86 | str_value.charset(), str_value.ptr(), | |
| 4144 | 172 | str_value.ptr() + str_value.length(), unsigned_flag); | |
| 4145 | } | ||
| 4146 | 2 | case MYSQL_TYPE_DATE: | |
| 4147 | case MYSQL_TYPE_TIME: | ||
| 4148 | case MYSQL_TYPE_DATETIME: | ||
| 4149 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | return (longlong)propagate_datetime_overflow(current_thd, [&](int *w) { |
| 4150 | 2 | return TIME_to_ulonglong_round(value.time, w); | |
| 4151 | 2 | }); | |
| 4152 | ✗ | default: | |
| 4153 | ✗ | assert(0); | |
| 4154 | } | ||
| 4155 | return 0; | ||
| 4156 | } | ||
| 4157 | |||
| 4158 | 1402 | my_decimal *Item_param::val_decimal(my_decimal *dec) { | |
| 4159 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
|
1402 | assert(data_type() != MYSQL_TYPE_INVALID); |
| 4160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
|
1402 | assert(param_state() != NO_VALUE); |
| 4161 | |||
| 4162 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1399 times.
|
1402 | if (param_state() == NULL_VALUE) { |
| 4163 | 3 | return nullptr; | |
| 4164 | } | ||
| 4165 |
4/6✓ Branch 0 taken 1179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
1399 | switch (data_type_actual()) { |
| 4166 | 1179 | case MYSQL_TYPE_NEWDECIMAL: | |
| 4167 | 1179 | return &decimal_value; | |
| 4168 | ✗ | case MYSQL_TYPE_DOUBLE: | |
| 4169 | ✗ | double2my_decimal(E_DEC_FATAL_ERROR, value.real, dec); | |
| 4170 | ✗ | return dec; | |
| 4171 | 217 | case MYSQL_TYPE_LONGLONG: | |
| 4172 | 217 | int2my_decimal(E_DEC_FATAL_ERROR, value.integer, is_unsigned_actual(), | |
| 4173 | dec); | ||
| 4174 | 217 | return dec; | |
| 4175 | 1 | case MYSQL_TYPE_VARCHAR: | |
| 4176 | 1 | return val_decimal_from_string(dec); | |
| 4177 | 2 | case MYSQL_TYPE_DATE: | |
| 4178 | case MYSQL_TYPE_TIME: | ||
| 4179 | case MYSQL_TYPE_DATETIME: | ||
| 4180 | 2 | return date2my_decimal(&value.time, dec); | |
| 4181 | ✗ | default: | |
| 4182 | ✗ | assert(0); | |
| 4183 | } | ||
| 4184 | return nullptr; | ||
| 4185 | } | ||
| 4186 | |||
| 4187 | 3491 | String *Item_param::val_str(String *str) { | |
| 4188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3491 times.
|
3491 | assert(data_type() != MYSQL_TYPE_INVALID); |
| 4189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3491 times.
|
3491 | assert(param_state() != NO_VALUE); |
| 4190 | |||
| 4191 |
2/2✓ Branch 0 taken 165 times.
✓ Branch 1 taken 3326 times.
|
3491 | if (param_state() == NULL_VALUE) { |
| 4192 | 165 | return nullptr; | |
| 4193 | } | ||
| 4194 |
4/6✓ Branch 0 taken 3187 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
|
3326 | switch (data_type_actual()) { |
| 4195 | 3187 | case MYSQL_TYPE_VARCHAR: | |
| 4196 | 3187 | return &str_value_ptr; | |
| 4197 | ✗ | case MYSQL_TYPE_DOUBLE: | |
| 4198 | ✗ | str->set_real(value.real, DECIMAL_NOT_SPECIFIED, &my_charset_bin); | |
| 4199 | ✗ | return str; | |
| 4200 | 69 | case MYSQL_TYPE_LONGLONG: | |
| 4201 | 69 | str->set_int(value.integer, is_unsigned_actual(), &my_charset_bin); | |
| 4202 | 69 | return str; | |
| 4203 | 24 | case MYSQL_TYPE_NEWDECIMAL: | |
| 4204 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, str) <= 1) |
| 4205 | 24 | return str; | |
| 4206 | ✗ | return nullptr; | |
| 4207 | 46 | case MYSQL_TYPE_DATE: | |
| 4208 | case MYSQL_TYPE_TIME: | ||
| 4209 | case MYSQL_TYPE_DATETIME: { | ||
| 4210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (str->reserve(MAX_DATE_STRING_REP_LENGTH)) break; |
| 4211 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | str->length(my_TIME_to_str(value.time, str->ptr(), |
| 4212 | 46 | min(decimals, uint8{DATETIME_MAX_DECIMALS}))); | |
| 4213 | 46 | str->set_charset(&my_charset_bin); | |
| 4214 | 46 | return str; | |
| 4215 | } | ||
| 4216 | ✗ | default: | |
| 4217 | ✗ | assert(0); | |
| 4218 | } | ||
| 4219 | ✗ | return str; | |
| 4220 | } | ||
| 4221 | |||
| 4222 | 116 | bool Item_param::val_json(Json_wrapper *wr) { | |
| 4223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
|
116 | assert(fixed); |
| 4224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
|
116 | assert(data_type() != MYSQL_TYPE_INVALID); |
| 4225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
|
116 | assert(param_state() != NO_VALUE); |
| 4226 | |||
| 4227 | 116 | String value; | |
| 4228 | 116 | String tmp; | |
| 4229 | 232 | return sql_scalar_to_json(this, "cast_as_json", &value, &tmp, wr, nullptr, | |
| 4230 |
1/2✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
|
232 | m_json_as_scalar); |
| 4231 | 116 | } | |
| 4232 | |||
| 4233 | 2344 | void Item_param::copy_param_actual_type(Item_param *from) { | |
| 4234 | 2344 | set_data_type_source(from->data_type_source(), from->is_unsigned_actual()); | |
| 4235 | 2344 | set_data_type_actual(from->data_type_actual(), from->is_unsigned_actual()); | |
| 4236 | 2344 | m_collation_source = from->m_collation_source; | |
| 4237 | 2344 | m_collation_actual = from->m_collation_actual; | |
| 4238 | 2344 | m_param_state = from->m_param_state; | |
| 4239 | /* | ||
| 4240 | In a repreparation, steps are: | ||
| 4241 | - parse, create new Item_param | ||
| 4242 | - copy_param_actual_type (sets m_param_state from old param, that makes it | ||
| 4243 | look like it has a value) | ||
| 4244 | - prepare_query() | ||
| 4245 | - swap_parameter_array() (sets value from old param). | ||
| 4246 | So, here the new Item_param is in a split-brain state. | ||
| 4247 | Thus in prepare_query() the optimizer tracing will try to print its value; | ||
| 4248 | so the not-yet-final value has to be reasonable; if we leave it random here | ||
| 4249 | we can crash (if using DECIMAL) (see query_val_str()). | ||
| 4250 | We do not copy any pointer-to-data (e.g. str_value), to have no problems | ||
| 4251 | with memory ownership. | ||
| 4252 | */ | ||
| 4253 | 2344 | value = from->value; | |
| 4254 |
2/2✓ Branch 0 taken 556 times.
✓ Branch 1 taken 1788 times.
|
2344 | switch (m_param_state) { |
| 4255 | 556 | case DECIMAL_VALUE: | |
| 4256 | // Propagate decimals' layout, and set number to zero | ||
| 4257 | 556 | decimal_value.intg = from->decimal_value.intg; | |
| 4258 | 556 | decimal_value.frac = from->decimal_value.frac; | |
| 4259 | 556 | memset(decimal_value.buf, 0, DECIMAL_BUFF_LENGTH); | |
| 4260 | 556 | decimal_value.sign(from->decimal_value.sign()); | |
| 4261 | 556 | break; | |
| 4262 | // STRING_VALUE: str_value member was initialized by ctor already. | ||
| 4263 | 1788 | default: | |
| 4264 | 1788 | break; | |
| 4265 | } | ||
| 4266 | 2344 | } | |
| 4267 | |||
| 4268 | /** | ||
| 4269 | Return Param item values in string format, for generating the dynamic | ||
| 4270 | query used in update/binary logs. | ||
| 4271 | |||
| 4272 | @param thd current thread | ||
| 4273 | @param[out] str String to fill with parameter | ||
| 4274 | |||
| 4275 | @returns supplied string on success, NULL on error | ||
| 4276 | |||
| 4277 | @todo | ||
| 4278 | - Change interface and implementation to fill log data in place | ||
| 4279 | and avoid one more memcpy/alloc between str and log string. | ||
| 4280 | - In case of error we need to notify replication | ||
| 4281 | that binary log contains wrong statement | ||
| 4282 | */ | ||
| 4283 | |||
| 4284 | 150298 | const String *Item_param::query_val_str(const THD *thd, String *str) const { | |
| 4285 |
6/7✓ Branch 0 taken 9005 times.
✓ Branch 1 taken 132099 times.
✓ Branch 2 taken 1371 times.
✓ Branch 3 taken 221 times.
✓ Branch 4 taken 6473 times.
✓ Branch 5 taken 1129 times.
✗ Branch 6 not taken.
|
150298 | switch (m_param_state) { |
| 4286 | 9005 | case INT_VALUE: | |
| 4287 | 9005 | str->set_int(value.integer, is_unsigned_actual(), &my_charset_bin); | |
| 4288 | 9004 | break; | |
| 4289 | 132099 | case REAL_VALUE: | |
| 4290 | 132099 | str->set_real(value.real, DECIMAL_NOT_SPECIFIED, &my_charset_bin); | |
| 4291 | 132099 | break; | |
| 4292 | 1371 | case DECIMAL_VALUE: | |
| 4293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1371 times.
|
1371 | if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, str) > 1) |
| 4294 | ✗ | return &my_null_string; | |
| 4295 | 1371 | break; | |
| 4296 | 221 | case TIME_VALUE: { | |
| 4297 | char *buf, *ptr; | ||
| 4298 | 221 | str->length(0); | |
| 4299 | /* | ||
| 4300 | TODO: in case of error we need to notify replication | ||
| 4301 | that binary log contains wrong statement | ||
| 4302 | */ | ||
| 4303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
|
221 | if (str->reserve(MAX_DATE_STRING_REP_LENGTH + 3)) break; |
| 4304 | |||
| 4305 | /* Create date string inplace */ | ||
| 4306 | 221 | buf = str->c_ptr_quick(); | |
| 4307 | 221 | ptr = buf; | |
| 4308 | 221 | *ptr++ = '\''; | |
| 4309 | 442 | ptr += my_TIME_to_str(value.time, ptr, | |
| 4310 |
1/2✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
|
221 | min(decimals, uint8{DATETIME_MAX_DECIMALS})); |
| 4311 | 221 | *ptr++ = '\''; | |
| 4312 | 221 | str->length((uint32)(ptr - buf)); | |
| 4313 | 221 | break; | |
| 4314 | } | ||
| 4315 | 6473 | case STRING_VALUE: | |
| 4316 | case LONG_DATA_VALUE: { | ||
| 4317 | 6473 | str->length(0); | |
| 4318 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6474 times.
|
6473 | if (append_query_string(thd, thd->variables.character_set_client, |
| 4319 | &str_value, str)) | ||
| 4320 | ✗ | return nullptr; | |
| 4321 | 6474 | break; | |
| 4322 | } | ||
| 4323 | 1129 | case NULL_VALUE: | |
| 4324 | 1129 | return &my_null_string; | |
| 4325 | ✗ | default: | |
| 4326 | ✗ | assert(0); | |
| 4327 | } | ||
| 4328 | 149169 | return str; | |
| 4329 | } | ||
| 4330 | |||
| 4331 | /** | ||
| 4332 | Convert value according to the following rules: | ||
| 4333 | - Convert string from client character set to the character set of | ||
| 4334 | connection. | ||
| 4335 | - Invalid character set conversions cause an error. | ||
| 4336 | - If resolved type is a temporal value, attempt to interpret string | ||
| 4337 | or numeric value as temporal value and set actual type accordingly. | ||
| 4338 | - Invalid conversions to temporal values are currently ignored and | ||
| 4339 | will cause neither errors nor warnings, and actual type is left | ||
| 4340 | unchanged. It is expected that later processing will issue error | ||
| 4341 | or warning as appropriate. | ||
| 4342 | |||
| 4343 | @returns false if success, true if error | ||
| 4344 | */ | ||
| 4345 | |||
| 4346 | 149755 | bool Item_param::convert_value() { | |
| 4347 |
6/7✓ Branch 0 taken 8825 times.
✓ Branch 1 taken 1286 times.
✓ Branch 2 taken 131940 times.
✓ Branch 3 taken 221 times.
✓ Branch 4 taken 6358 times.
✓ Branch 5 taken 1126 times.
✗ Branch 6 not taken.
|
149755 | switch (data_type_actual()) { |
| 4348 | 8825 | case MYSQL_TYPE_LONGLONG: | |
| 4349 | /* | ||
| 4350 | If a temporal value is expected and the provided integer value can | ||
| 4351 | be converted to one, change the actual value accordingly. | ||
| 4352 | */ | ||
| 4353 |
6/6✓ Branch 0 taken 8812 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 8787 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 8787 times.
|
17637 | if (data_type() == MYSQL_TYPE_DATE || |
| 4354 | 8812 | data_type() == MYSQL_TYPE_DATETIME) { | |
| 4355 | 38 | int status = 0; | |
| 4356 | MYSQL_TIME t; | ||
| 4357 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (number_to_datetime(value.integer, &t, TIME_FUZZY_DATE, &status) == |
| 4358 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 6 times.
|
44 | -1LL || |
| 4359 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | status != 0) { |
| 4360 | 32 | break; | |
| 4361 | } | ||
| 4362 | 6 | value.time = t; | |
| 4363 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | if (value.time.time_type == MYSQL_TIMESTAMP_DATE) { |
| 4364 | 4 | set_data_type_actual(MYSQL_TYPE_DATE); | |
| 4365 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4366 | 2 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4367 | ✗ | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ) { | |
| 4368 | ✗ | if (convert_time_zone_displacement(current_thd->time_zone(), | |
| 4369 | &value.time)) | ||
| 4370 | 6 | return true; | |
| 4371 | ✗ | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4372 | } else { | ||
| 4373 | // We only expect DATE and DATETIME values, not TIME. | ||
| 4374 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_DATE || | |
| 4375 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME); | ||
| 4376 | } | ||
| 4377 | 6 | return false; | |
| 4378 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8771 times.
|
8787 | } else if (data_type() == MYSQL_TYPE_TIME) { |
| 4379 | 14 | int status = 0; | |
| 4380 | MYSQL_TIME t; | ||
| 4381 |
6/8✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 3 times.
|
14 | if (number_to_time(value.integer, &t, &status) || status != 0) { |
| 4382 | 10 | break; | |
| 4383 | } | ||
| 4384 | 3 | value.time = t; | |
| 4385 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (value.time.time_type == MYSQL_TIMESTAMP_TIME) { |
| 4386 | 2 | set_data_type_actual(MYSQL_TYPE_TIME); | |
| 4387 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4388 | 1 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4389 | } else { | ||
| 4390 | // We only expect TIME and DATETIME values, not DATE. | ||
| 4391 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_TIME || | |
| 4392 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME); | ||
| 4393 | } | ||
| 4394 | 3 | return false; | |
| 4395 | } | ||
| 4396 | 8771 | break; | |
| 4397 | |||
| 4398 | 1286 | case MYSQL_TYPE_NEWDECIMAL: | |
| 4399 | /* | ||
| 4400 | If a temporal value is expected and the provided decimal value can | ||
| 4401 | be converted to one, change the actual value accordingly. | ||
| 4402 | */ | ||
| 4403 |
6/6✓ Branch 0 taken 1283 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1278 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 1278 times.
|
2569 | if (data_type() == MYSQL_TYPE_DATE || |
| 4404 | 1283 | data_type() == MYSQL_TYPE_DATETIME) { | |
| 4405 | MYSQL_TIME t; | ||
| 4406 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (decimal_to_datetime(&decimal_value, &t, TIME_FUZZY_DATE)) { |
| 4407 | ✗ | break; | |
| 4408 | } | ||
| 4409 | 8 | value.time = t; | |
| 4410 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (value.time.time_type == MYSQL_TIMESTAMP_DATE) { |
| 4411 | 4 | set_data_type_actual(MYSQL_TYPE_DATE); | |
| 4412 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4413 | 4 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4414 | ✗ | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ) { | |
| 4415 | ✗ | if (convert_time_zone_displacement(current_thd->time_zone(), | |
| 4416 | &value.time)) | ||
| 4417 | 8 | return true; | |
| 4418 | ✗ | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4419 | } else { | ||
| 4420 | // We only expect DATE and DATETIME values, not TIME. | ||
| 4421 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_DATE || | |
| 4422 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME); | ||
| 4423 | } | ||
| 4424 | 8 | return false; | |
| 4425 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1274 times.
|
1278 | } else if (data_type() == MYSQL_TYPE_TIME) { |
| 4426 | MYSQL_TIME t; | ||
| 4427 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
|
4 | if (decimal_to_time(&decimal_value, &t)) { |
| 4428 | 1 | break; | |
| 4429 | } | ||
| 4430 | 3 | value.time = t; | |
| 4431 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (value.time.time_type == MYSQL_TIMESTAMP_TIME) { |
| 4432 | 2 | set_data_type_actual(MYSQL_TYPE_TIME); | |
| 4433 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4434 | 1 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4435 | } else { | ||
| 4436 | // We only expect TIME and DATETIME values, not DATE. | ||
| 4437 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_TIME || | |
| 4438 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME); | ||
| 4439 | } | ||
| 4440 | 3 | return false; | |
| 4441 | } | ||
| 4442 | 1274 | break; | |
| 4443 | |||
| 4444 | 131940 | case MYSQL_TYPE_DOUBLE: | |
| 4445 | /* | ||
| 4446 | If a temporal value is expected and the provided float value can | ||
| 4447 | be converted to one, change the actual value accordingly. | ||
| 4448 | */ | ||
| 4449 |
6/6✓ Branch 0 taken 131928 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 131903 times.
✓ Branch 4 taken 37 times.
✓ Branch 5 taken 131903 times.
|
263868 | if (data_type() == MYSQL_TYPE_DATE || |
| 4450 | 131928 | data_type() == MYSQL_TYPE_DATETIME) { | |
| 4451 | MYSQL_TIME t; | ||
| 4452 |
2/4✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
|
37 | if (double_to_datetime(value.real, &t, TIME_FUZZY_DATE)) { |
| 4453 | ✗ | break; | |
| 4454 | } | ||
| 4455 | 37 | value.time = t; | |
| 4456 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 33 times.
|
37 | if (value.time.time_type == MYSQL_TIMESTAMP_DATE) { |
| 4457 | 4 | set_data_type_actual(MYSQL_TYPE_DATE); | |
| 4458 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4459 | 33 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4460 | ✗ | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ) { | |
| 4461 | ✗ | if (convert_time_zone_displacement(current_thd->time_zone(), | |
| 4462 | &value.time)) | ||
| 4463 | 37 | return true; | |
| 4464 | ✗ | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4465 | } else { | ||
| 4466 | // We only expect DATE and DATETIME values, not TIME. | ||
| 4467 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_DATE || | |
| 4468 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME); | ||
| 4469 | } | ||
| 4470 | 37 | return false; | |
| 4471 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 131890 times.
|
131903 | } else if (data_type() == MYSQL_TYPE_TIME) { |
| 4472 | MYSQL_TIME t; | ||
| 4473 |
3/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3 times.
|
13 | if (double_to_time(value.real, &t)) { |
| 4474 | 10 | break; | |
| 4475 | } | ||
| 4476 | 3 | value.time = t; | |
| 4477 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (value.time.time_type == MYSQL_TIMESTAMP_TIME) { |
| 4478 | 2 | set_data_type_actual(MYSQL_TYPE_TIME); | |
| 4479 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4480 | 1 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4481 | } else { | ||
| 4482 | // We only expect TIME and DATETIME values, not DATE. | ||
| 4483 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_TIME || | |
| 4484 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME); | ||
| 4485 | } | ||
| 4486 | 3 | return false; | |
| 4487 | } | ||
| 4488 | 131890 | break; | |
| 4489 | |||
| 4490 | 221 | case MYSQL_TYPE_DATE: | |
| 4491 | case MYSQL_TYPE_TIME: | ||
| 4492 | case MYSQL_TYPE_DATETIME: | ||
| 4493 | 221 | break; | |
| 4494 | |||
| 4495 | 6358 | case MYSQL_TYPE_VARCHAR: | |
| 4496 |
2/2✓ Branch 0 taken 4745 times.
✓ Branch 1 taken 1614 times.
|
6358 | if (is_string_type(data_type())) { |
| 4497 | size_t dummy; | ||
| 4498 |
3/4✓ Branch 0 taken 4745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✓ Branch 3 taken 4526 times.
|
4745 | if (String::needs_conversion(0, m_collation_source, m_collation_actual, |
| 4499 | &dummy)) { | ||
| 4500 | uint errors; | ||
| 4501 | 219 | StringBuffer<STRING_BUFFER_USUAL_SIZE> convert_buffer; | |
| 4502 |
2/4✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
|
219 | if (convert_buffer.copy(str_value.ptr(), str_value.length(), |
| 4503 | m_collation_source, m_collation_actual, | ||
| 4504 | &errors)) | ||
| 4505 | ✗ | return true; | |
| 4506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
|
219 | if (errors > 0) { |
| 4507 | ✗ | my_error(ER_IMPOSSIBLE_STRING_CONVERSION, MYF(0), | |
| 4508 | ✗ | m_collation_source->m_coll_name, | |
| 4509 | ✗ | m_collation_actual->m_coll_name, "parameter"); | |
| 4510 | ✗ | return true; | |
| 4511 | } | ||
| 4512 |
2/4✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
|
219 | if (str_value.copy(convert_buffer)) return true; |
| 4513 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | } else { |
| 4514 | 4526 | str_value.set_charset(m_collation_actual); | |
| 4515 | } | ||
| 4516 |
2/2✓ Branch 0 taken 1338 times.
✓ Branch 1 taken 276 times.
|
1614 | } else if (is_numeric_type(data_type())) { |
| 4517 | 1338 | const char *ptr = str_value.ptr(); | |
| 4518 | 1338 | size_t length = str_value.length(); | |
| 4519 | 1338 | const CHARSET_INFO *cs = m_collation_source; | |
| 4520 | int error; | ||
| 4521 | const char *endptr; | ||
| 4522 | 1338 | bool check_integer = is_integer_type(data_type()); | |
| 4523 |
2/2✓ Branch 0 taken 609 times.
✓ Branch 1 taken 729 times.
|
1338 | if (check_integer) { |
| 4524 | // First, check if string is a signed or unsigned integer | ||
| 4525 | 609 | endptr = ptr + length; | |
| 4526 |
1/2✓ Branch 0 taken 609 times.
✗ Branch 1 not taken.
|
609 | value.integer = (*(cs->cset->strtoll10))(cs, ptr, &endptr, &error); |
| 4527 |
4/4✓ Branch 0 taken 162 times.
✓ Branch 1 taken 447 times.
✓ Branch 2 taken 449 times.
✓ Branch 3 taken 160 times.
|
771 | if (length == static_cast<size_t>(endptr - ptr) || |
| 4528 |
3/4✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 160 times.
|
162 | check_if_only_end_space(cs, endptr, ptr + length)) { |
| 4529 |
6/6✓ Branch 0 taken 361 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 359 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 303 times.
✓ Branch 5 taken 56 times.
|
449 | if (!unsigned_flag && error <= 0 && value.integer >= 0) { |
| 4530 | 303 | set_data_type_actual(MYSQL_TYPE_LONGLONG, false); | |
| 4531 | 1184 | return false; | |
| 4532 |
4/4✓ Branch 0 taken 88 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 40 times.
|
146 | } else if (unsigned_flag && error == 0) { |
| 4533 | 48 | set_data_type_actual(MYSQL_TYPE_LONGLONG, true); | |
| 4534 | 48 | return false; | |
| 4535 | } | ||
| 4536 | } | ||
| 4537 | } | ||
| 4538 | // Next, check if it is a decimal | ||
| 4539 |
6/6✓ Branch 0 taken 729 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 280 times.
✓ Branch 3 taken 449 times.
✓ Branch 4 taken 538 times.
✓ Branch 5 taken 449 times.
|
987 | if (check_integer || data_type() == MYSQL_TYPE_NEWDECIMAL) { |
| 4540 |
3/4✓ Branch 0 taken 538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 404 times.
✓ Branch 3 taken 134 times.
|
538 | if (str2my_decimal(E_DEC_ERROR, ptr, length, cs, &decimal_value) == |
| 4541 | E_DEC_OK) { | ||
| 4542 | 404 | set_data_type_actual(MYSQL_TYPE_NEWDECIMAL); | |
| 4543 | 404 | return false; | |
| 4544 | } | ||
| 4545 | } | ||
| 4546 | // Finally, check if it is a valid floating point value | ||
| 4547 |
1/2✓ Branch 0 taken 583 times.
✗ Branch 1 not taken.
|
583 | value.real = my_strntod(cs, ptr, length, &endptr, &error); |
| 4548 | 1749 | if (error == 0 && | |
| 4549 |
5/6✓ Branch 0 taken 583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 438 times.
✓ Branch 3 taken 145 times.
✓ Branch 4 taken 429 times.
✓ Branch 5 taken 154 times.
|
1021 | endptr - ptr > 0 && // my_strntod() accepts empty string as 0.0e0 |
| 4550 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 427 times.
|
438 | (length == static_cast<size_t>(endptr - ptr) || |
| 4551 |
3/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
|
11 | check_if_only_end_space(cs, endptr, ptr + length))) { |
| 4552 | 429 | set_data_type_actual(MYSQL_TYPE_DOUBLE); | |
| 4553 | 429 | return false; | |
| 4554 | } | ||
| 4555 |
6/6✓ Branch 0 taken 221 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 127 times.
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 182 times.
✓ Branch 5 taken 94 times.
|
497 | } else if (data_type() == MYSQL_TYPE_DATE || |
| 4556 | 221 | data_type() == MYSQL_TYPE_DATETIME) { | |
| 4557 | 182 | str_value.set_charset(m_collation_source); | |
| 4558 | 182 | MYSQL_TIME_STATUS status; | |
| 4559 |
1/2✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
|
182 | if (str_to_datetime(&str_value, &value.time, TIME_FUZZY_DATE, |
| 4560 |
4/4✓ Branch 0 taken 153 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 153 times.
✓ Branch 3 taken 29 times.
|
335 | &status) || |
| 4561 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 153 times.
|
153 | status.warnings != 0) { |
| 4562 | // Nothing | ||
| 4563 | } else { | ||
| 4564 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 138 times.
|
153 | if (value.time.time_type == MYSQL_TIMESTAMP_DATE) { |
| 4565 | 15 | set_data_type_actual(MYSQL_TYPE_DATE); | |
| 4566 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 4 times.
|
138 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4567 | 134 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4568 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ) { |
| 4569 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
|
4 | if (convert_time_zone_displacement(current_thd->time_zone(), |
| 4570 | &value.time)) | ||
| 4571 | 153 | return true; | |
| 4572 | 4 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4573 | } else { | ||
| 4574 | // We only expect DATE and DATETIME values, not TIME. | ||
| 4575 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_DATE || | |
| 4576 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME || | ||
| 4577 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ); | ||
| 4578 | } | ||
| 4579 | 153 | return false; | |
| 4580 | } | ||
| 4581 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 39 times.
|
94 | } else if (data_type() == MYSQL_TYPE_TIME) { |
| 4582 | 55 | str_value.set_charset(m_collation_source); | |
| 4583 | 55 | MYSQL_TIME_STATUS status; | |
| 4584 |
5/6✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 5 times.
|
107 | if (str_to_time(&str_value, &value.time, 0, &status) || |
| 4585 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
|
52 | status.warnings != 0) { |
| 4586 | } else { | ||
| 4587 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 41 times.
|
50 | if (value.time.time_type == MYSQL_TIMESTAMP_TIME) { |
| 4588 | 9 | set_data_type_actual(MYSQL_TYPE_TIME); | |
| 4589 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
|
41 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME) { |
| 4590 | 39 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4591 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | } else if (value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ) { |
| 4592 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | if (convert_time_zone_displacement(current_thd->time_zone(), |
| 4593 | &value.time)) | ||
| 4594 | 50 | return true; | |
| 4595 | 2 | set_data_type_actual(MYSQL_TYPE_DATETIME); | |
| 4596 | } else { | ||
| 4597 | // We only expect TIME and DATETIME values, not DATE. | ||
| 4598 | ✗ | assert(value.time.time_type == MYSQL_TIMESTAMP_TIME || | |
| 4599 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME || | ||
| 4600 | value.time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ); | ||
| 4601 | } | ||
| 4602 | 50 | return false; | |
| 4603 | } | ||
| 4604 | } | ||
| 4605 | /* | ||
| 4606 | str_value_ptr is returned from val_str(). It must not be allocated | ||
| 4607 | to prevent it's modification by val_str() invoker. | ||
| 4608 | */ | ||
| 4609 | 4970 | str_value_ptr.set(str_value.ptr(), str_value.length(), | |
| 4610 | str_value.charset()); | ||
| 4611 | 4972 | break; | |
| 4612 | |||
| 4613 | 1126 | case MYSQL_TYPE_NULL: | |
| 4614 | 1126 | break; | |
| 4615 | ✗ | default: | |
| 4616 | ✗ | assert(false); | |
| 4617 | } | ||
| 4618 | 148307 | return false; | |
| 4619 | } | ||
| 4620 | |||
| 4621 | ✗ | Item *Item_param::clone_item() const { | |
| 4622 | /* see comments in the header file */ | ||
| 4623 | ✗ | switch (m_param_state) { | |
| 4624 | ✗ | case NULL_VALUE: | |
| 4625 | ✗ | return new Item_null(item_name); | |
| 4626 | ✗ | case INT_VALUE: | |
| 4627 | ✗ | return (is_unsigned_actual() | |
| 4628 | ✗ | ? new Item_uint(item_name, value.integer, max_length) | |
| 4629 | ✗ | : new Item_int(item_name, value.integer, max_length)); | |
| 4630 | ✗ | case REAL_VALUE: | |
| 4631 | ✗ | return new Item_float(item_name, value.real, decimals, max_length); | |
| 4632 | ✗ | case STRING_VALUE: | |
| 4633 | case LONG_DATA_VALUE: | ||
| 4634 | ✗ | return new Item_string(item_name, str_value.ptr(), str_value.length(), | |
| 4635 | ✗ | str_value.charset()); | |
| 4636 | ✗ | case TIME_VALUE: | |
| 4637 | ✗ | break; | |
| 4638 | ✗ | case NO_VALUE: | |
| 4639 | default: | ||
| 4640 | ✗ | assert(0); | |
| 4641 | }; | ||
| 4642 | ✗ | return nullptr; | |
| 4643 | } | ||
| 4644 | |||
| 4645 | 906 | bool Item_param::eq(const Item *arg, bool) const { return this == arg; } | |
| 4646 | |||
| 4647 | /* End of Item_param related */ | ||
| 4648 | |||
| 4649 | 2264 | void Item_param::print(const THD *thd, String *str, | |
| 4650 | enum_query_type query_type) const { | ||
| 4651 |
2/2✓ Branch 0 taken 547 times.
✓ Branch 1 taken 1717 times.
|
2264 | if (m_param_state == NO_VALUE || |
| 4652 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 542 times.
|
547 | query_type & (QT_NORMALIZED_FORMAT | QT_NO_DATA_EXPANSION)) { |
| 4653 | 1722 | str->append('?'); | |
| 4654 | } else { | ||
| 4655 | char buffer[STRING_BUFFER_USUAL_SIZE]; | ||
| 4656 | 542 | String tmp(buffer, sizeof(buffer), &my_charset_bin); | |
| 4657 |
1/2✓ Branch 0 taken 542 times.
✗ Branch 1 not taken.
|
542 | const String *res = query_val_str(thd, &tmp); |
| 4658 |
2/4✓ Branch 0 taken 542 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 542 times.
✗ Branch 3 not taken.
|
542 | if (res != nullptr) str->append(*res); |
| 4659 | 542 | } | |
| 4660 | 2264 | } | |
| 4661 | |||
| 4662 | /** | ||
| 4663 | Preserve the original parameter types and values | ||
| 4664 | when re-preparing a prepared statement. | ||
| 4665 | |||
| 4666 | @details Copy parameter type information and conversion | ||
| 4667 | function pointers from a parameter of the old statement | ||
| 4668 | to the corresponding parameter of the new one. | ||
| 4669 | |||
| 4670 | Move parameter values from the old parameters to the new | ||
| 4671 | one. We simply "exchange" the values, which allows | ||
| 4672 | to save on allocation and character set conversion in | ||
| 4673 | case a parameter is a string or a blob/clob. | ||
| 4674 | |||
| 4675 | The old parameter gets the value of this one, which | ||
| 4676 | ensures that all memory of this parameter is freed | ||
| 4677 | correctly. | ||
| 4678 | |||
| 4679 | @param[in] src parameter item of the original | ||
| 4680 | prepared statement | ||
| 4681 | */ | ||
| 4682 | |||
| 4683 | 2343 | void Item_param::set_param_type_and_swap_value(Item_param *src) { | |
| 4684 | 2343 | m_data_type_source = src->m_data_type_source; | |
| 4685 | 2343 | m_data_type_actual = src->m_data_type_actual; | |
| 4686 | 2343 | m_unsigned_actual = src->m_unsigned_actual; | |
| 4687 | 2343 | m_collation_source = src->m_collation_source; | |
| 4688 | 2343 | m_collation_actual = src->m_collation_actual; | |
| 4689 | |||
| 4690 | 2343 | null_value = src->null_value; | |
| 4691 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2343 times.
|
2343 | assert(m_param_state == src->m_param_state); |
| 4692 | 2343 | value = src->value; | |
| 4693 | |||
| 4694 | 2343 | decimal_value.swap(src->decimal_value); | |
| 4695 | 2343 | str_value.swap(src->str_value); | |
| 4696 | 2343 | str_value_ptr.swap(src->str_value_ptr); | |
| 4697 | 2343 | } | |
| 4698 | |||
| 4699 | /** | ||
| 4700 | This operation is intended to store some item value in Item_param to be | ||
| 4701 | used later. | ||
| 4702 | |||
| 4703 | @param it a pointer to an item in the tree | ||
| 4704 | |||
| 4705 | @return Error status | ||
| 4706 | @retval true on error | ||
| 4707 | @retval false on success | ||
| 4708 | */ | ||
| 4709 | |||
| 4710 | 226 | bool Item_param::set_value(THD *, sp_rcontext *, Item **it) { | |
| 4711 | 226 | Item *arg = *it; | |
| 4712 | |||
| 4713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
|
226 | if (arg->is_null()) { |
| 4714 | ✗ | set_null(); | |
| 4715 | ✗ | return false; | |
| 4716 | } | ||
| 4717 | |||
| 4718 | 226 | null_value = false; | |
| 4719 | |||
| 4720 |
4/5✓ Branch 0 taken 79 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
|
226 | switch (arg->result_type()) { |
| 4721 | 79 | case STRING_RESULT: { | |
| 4722 | char str_buffer[STRING_BUFFER_USUAL_SIZE]; | ||
| 4723 | 79 | String sv_buffer(str_buffer, sizeof(str_buffer), &my_charset_bin); | |
| 4724 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | String *sv = arg->val_str(&sv_buffer); |
| 4725 | |||
| 4726 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | if (!sv) return true; |
| 4727 | |||
| 4728 |
2/4✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
|
79 | set_str(sv->c_ptr_safe(), sv->length()); |
| 4729 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | str_value_ptr.set(str_value.ptr(), str_value.length(), |
| 4730 | str_value.charset()); | ||
| 4731 | 79 | collation.set(str_value.charset(), DERIVATION_COERCIBLE); | |
| 4732 | 79 | break; | |
| 4733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | } |
| 4734 | |||
| 4735 | 24 | case REAL_RESULT: | |
| 4736 | 24 | set_double(arg->val_real()); | |
| 4737 | 24 | break; | |
| 4738 | |||
| 4739 | 103 | case INT_RESULT: | |
| 4740 | 103 | set_int(arg->val_int()); | |
| 4741 | 103 | break; | |
| 4742 | |||
| 4743 | 20 | case DECIMAL_RESULT: { | |
| 4744 | 20 | my_decimal dv_buf; | |
| 4745 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_decimal *dv = arg->val_decimal(&dv_buf); |
| 4746 | |||
| 4747 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if (!dv) return true; |
| 4748 | |||
| 4749 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | set_decimal(dv); |
| 4750 | 20 | break; | |
| 4751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | } |
| 4752 | |||
| 4753 | ✗ | default: | |
| 4754 | /* That can not happen. */ | ||
| 4755 | |||
| 4756 | ✗ | assert(false); // Abort in debug mode. | |
| 4757 | |||
| 4758 | set_null(); // Set to NULL in release mode. | ||
| 4759 | return false; | ||
| 4760 | } | ||
| 4761 | |||
| 4762 | 226 | return false; | |
| 4763 | } | ||
| 4764 | |||
| 4765 | /** | ||
| 4766 | Setter of Item_param::m_out_param_info. | ||
| 4767 | |||
| 4768 | m_out_param_info is used to store information about store routine | ||
| 4769 | OUT-parameters, such as stored routine name, database, stored routine | ||
| 4770 | variable name. It is supposed to be set in sp_head::execute() after | ||
| 4771 | Item_param::set_value() is called. | ||
| 4772 | */ | ||
| 4773 | |||
| 4774 | 226 | void Item_param::set_out_param_info(Send_field *info) { | |
| 4775 | 226 | m_out_param_info = info; | |
| 4776 | /* | ||
| 4777 | Here we set data type for an already fixed Item object. | ||
| 4778 | It should rather be set when resolving the CALL statement. | ||
| 4779 | */ | ||
| 4780 | 226 | set_data_type(m_out_param_info->type); | |
| 4781 | 226 | m_result_type = Field::result_merge_type(data_type()); | |
| 4782 | 226 | } | |
| 4783 | |||
| 4784 | /** | ||
| 4785 | Getter of Item_param::m_out_param_info. | ||
| 4786 | |||
| 4787 | m_out_param_info is used to store information about store routine | ||
| 4788 | OUT-parameters, such as stored routine name, database, stored routine | ||
| 4789 | variable name. It is supposed to be retrieved in | ||
| 4790 | Protocol::send_parameters() during creation of OUT-parameter result set. | ||
| 4791 | */ | ||
| 4792 | |||
| 4793 | 258 | const Send_field *Item_param::get_out_param_info() const { | |
| 4794 | 258 | return m_out_param_info; | |
| 4795 | } | ||
| 4796 | |||
| 4797 | /** | ||
| 4798 | Fill meta-data information for the corresponding column in a result set. | ||
| 4799 | If this is an OUT-parameter of a stored procedure, preserve meta-data of | ||
| 4800 | stored-routine variable. | ||
| 4801 | |||
| 4802 | @param field container for meta-data to be filled | ||
| 4803 | */ | ||
| 4804 | |||
| 4805 | 134672 | void Item_param::make_field(Send_field *field) { | |
| 4806 | 134672 | Item::make_field(field); | |
| 4807 | |||
| 4808 |
2/2✓ Branch 0 taken 134507 times.
✓ Branch 1 taken 165 times.
|
134672 | if (!m_out_param_info) return; |
| 4809 | |||
| 4810 | /* | ||
| 4811 | This is an OUT-parameter of stored procedure. We should use | ||
| 4812 | OUT-parameter info to fill out the names. | ||
| 4813 | */ | ||
| 4814 | |||
| 4815 | 165 | field->db_name = m_out_param_info->db_name; | |
| 4816 | 165 | field->table_name = m_out_param_info->table_name; | |
| 4817 | 165 | field->org_table_name = m_out_param_info->org_table_name; | |
| 4818 | 165 | field->col_name = m_out_param_info->col_name; | |
| 4819 | 165 | field->org_col_name = m_out_param_info->org_col_name; | |
| 4820 | |||
| 4821 | 165 | field->length = m_out_param_info->length; | |
| 4822 | 165 | field->charsetnr = m_out_param_info->charsetnr; | |
| 4823 | 165 | field->flags = m_out_param_info->flags; | |
| 4824 | 165 | field->decimals = m_out_param_info->decimals; | |
| 4825 | 165 | field->type = m_out_param_info->type; | |
| 4826 | } | ||
| 4827 | |||
| 4828 | /* | ||
| 4829 | Functions to convert item to field (for send_result_set_metadata) | ||
| 4830 | */ | ||
| 4831 | |||
| 4832 | 1952002 | bool Item::fix_fields(THD *, Item **) { | |
| 4833 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1952002 times.
|
1952002 | assert(is_contextualized()); |
| 4834 | |||
| 4835 | // We do not check fields which are fixed during construction | ||
| 4836 |
3/4✓ Branch 0 taken 1951250 times.
✓ Branch 1 taken 752 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1951250 times.
|
1952002 | assert(fixed == 0 || basic_const_item()); |
| 4837 | 1952002 | fixed = true; | |
| 4838 | 1952002 | return false; | |
| 4839 | } | ||
| 4840 | |||
| 4841 | 748 | double Item_ref_null_helper::val_real() { | |
| 4842 | 748 | auto tmp = super::val_real(); | |
| 4843 | 748 | owner->was_null |= null_value; | |
| 4844 | 748 | return tmp; | |
| 4845 | } | ||
| 4846 | |||
| 4847 | 1522 | longlong Item_ref_null_helper::val_int() { | |
| 4848 | 1522 | auto tmp = super::val_int(); | |
| 4849 | 1522 | owner->was_null |= null_value; | |
| 4850 | 1522 | return tmp; | |
| 4851 | } | ||
| 4852 | |||
| 4853 | 4 | longlong Item_ref_null_helper::val_time_temporal() { | |
| 4854 | 4 | auto tmp = super::val_time_temporal(); | |
| 4855 | 4 | owner->was_null |= null_value; | |
| 4856 | 4 | return tmp; | |
| 4857 | } | ||
| 4858 | |||
| 4859 | 393 | longlong Item_ref_null_helper::val_date_temporal() { | |
| 4860 | 393 | auto tmp = super::val_date_temporal(); | |
| 4861 | 393 | owner->was_null |= null_value; | |
| 4862 | 393 | return tmp; | |
| 4863 | } | ||
| 4864 | |||
| 4865 | 499 | my_decimal *Item_ref_null_helper::val_decimal(my_decimal *decimal_value) { | |
| 4866 | 499 | auto tmp = super::val_decimal(decimal_value); | |
| 4867 | 499 | owner->was_null |= null_value; | |
| 4868 | 499 | return tmp; | |
| 4869 | } | ||
| 4870 | |||
| 4871 | ✗ | bool Item_ref_null_helper::val_bool() { | |
| 4872 | ✗ | auto tmp = super::val_bool(); | |
| 4873 | ✗ | owner->was_null |= null_value; | |
| 4874 | ✗ | return tmp; | |
| 4875 | } | ||
| 4876 | |||
| 4877 | 2385 | String *Item_ref_null_helper::val_str(String *s) { | |
| 4878 | 2385 | auto tmp = super::val_str(s); | |
| 4879 | 2385 | owner->was_null |= null_value; | |
| 4880 | 2385 | return tmp; | |
| 4881 | } | ||
| 4882 | |||
| 4883 | ✗ | bool Item_ref_null_helper::get_date(MYSQL_TIME *ltime, | |
| 4884 | my_time_flags_t fuzzydate) { | ||
| 4885 | ✗ | auto tmp = super::get_date(ltime, fuzzydate); | |
| 4886 | ✗ | owner->was_null |= null_value; | |
| 4887 | ✗ | return tmp; | |
| 4888 | } | ||
| 4889 | |||
| 4890 | /** | ||
| 4891 | Mark item and Query_blocks as dependent if item was resolved in | ||
| 4892 | outer SELECT. | ||
| 4893 | |||
| 4894 | @param thd Current session. | ||
| 4895 | @param last select from which current item depend | ||
| 4896 | @param current current select | ||
| 4897 | @param resolved_item item which was resolved in outer SELECT | ||
| 4898 | @param mark_item item which should be marked; resolved_item will be | ||
| 4899 | marked anyway. | ||
| 4900 | */ | ||
| 4901 | |||
| 4902 | 13578 | static void mark_as_dependent(THD *thd, Query_block *last, Query_block *current, | |
| 4903 | Item_ident *resolved_item, | ||
| 4904 | Item_ident *mark_item) { | ||
| 4905 |
2/2✓ Branch 0 taken 13423 times.
✓ Branch 1 taken 155 times.
|
13578 | const char *db_name = (resolved_item->db_name ? resolved_item->db_name : ""); |
| 4906 | 13578 | const char *table_name = | |
| 4907 |
2/2✓ Branch 0 taken 13507 times.
✓ Branch 1 taken 71 times.
|
13578 | (resolved_item->table_name ? resolved_item->table_name : ""); |
| 4908 | /* store pointer on Query_block from which item is dependent */ | ||
| 4909 |
1/2✓ Branch 0 taken 13578 times.
✗ Branch 1 not taken.
|
13578 | if (mark_item) mark_item->depended_from = last; |
| 4910 | /* | ||
| 4911 | resolved_item is the one we are resolving (and we just found that it is an | ||
| 4912 | outer ref), its context is surely the subquery (see assertion below), so | ||
| 4913 | we set depended_from for it. | ||
| 4914 | */ | ||
| 4915 | 13578 | resolved_item->depended_from = last; | |
| 4916 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13578 times.
|
13578 | assert(resolved_item->context->query_block == current); |
| 4917 | |||
| 4918 | 13578 | current->mark_as_dependent(last, false); | |
| 4919 |
2/2✓ Branch 0 taken 486 times.
✓ Branch 1 taken 13092 times.
|
13578 | if (thd->lex->is_explain()) { |
| 4920 | /* | ||
| 4921 | UNION's result has select_number == INT_MAX which is printed as -1 and | ||
| 4922 | this is confusing. Instead, the number of the first SELECT in the UNION | ||
| 4923 | is printed as names in ORDER BY are resolved against select list of the | ||
| 4924 | first SELECT. | ||
| 4925 | */ | ||
| 4926 | 486 | uint sel_nr = (last->select_number < INT_MAX) | |
| 4927 |
2/2✓ Branch 0 taken 476 times.
✓ Branch 1 taken 10 times.
|
496 | ? last->select_number |
| 4928 | : last->master_query_expression() | ||
| 4929 | 10 | ->first_query_block() | |
| 4930 | 486 | ->select_number; | |
| 4931 | 972 | push_warning_printf(thd, Sql_condition::SL_NOTE, ER_WARN_FIELD_RESOLVED, | |
| 4932 | ER_THD(thd, ER_WARN_FIELD_RESOLVED), db_name, | ||
| 4933 |
2/2✓ Branch 0 taken 448 times.
✓ Branch 1 taken 38 times.
|
486 | (db_name[0] ? "." : ""), table_name, |
| 4934 |
2/2✓ Branch 0 taken 476 times.
✓ Branch 1 taken 10 times.
|
486 | (table_name[0] ? "." : ""), resolved_item->field_name, |
| 4935 | current->select_number, sel_nr); | ||
| 4936 | } | ||
| 4937 | 13578 | } | |
| 4938 | |||
| 4939 | /** | ||
| 4940 | Search a GROUP BY clause for a field with a certain name. | ||
| 4941 | |||
| 4942 | Search the GROUP BY list for a column named as find_item. When searching | ||
| 4943 | preference is given to columns that are qualified with the same table (and | ||
| 4944 | database) name as the one being searched for. | ||
| 4945 | |||
| 4946 | @param find_item the item being searched for | ||
| 4947 | @param group_list GROUP BY clause | ||
| 4948 | |||
| 4949 | @return | ||
| 4950 | - the found item on success | ||
| 4951 | - NULL if find_item is not in group_list | ||
| 4952 | */ | ||
| 4953 | |||
| 4954 | 681 | static Item **find_field_in_group_list(Item *find_item, ORDER *group_list) { | |
| 4955 | const char *db_name; | ||
| 4956 | const char *table_name; | ||
| 4957 | const char *field_name; | ||
| 4958 | 681 | ORDER *found_group = nullptr; | |
| 4959 | 681 | int found_match_degree = 0; | |
| 4960 | Item_ident *cur_field; | ||
| 4961 | 681 | int cur_match_degree = 0; | |
| 4962 | char name_buff[NAME_LEN + 1]; | ||
| 4963 | |||
| 4964 |
4/6✓ Branch 0 taken 681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 675 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 681 times.
✗ Branch 5 not taken.
|
1356 | if (find_item->type() == Item::FIELD_ITEM || |
| 4965 |
2/4✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 675 times.
✗ Branch 3 not taken.
|
675 | find_item->type() == Item::REF_ITEM) { |
| 4966 | 681 | db_name = ((Item_ident *)find_item)->db_name; | |
| 4967 | 681 | table_name = ((Item_ident *)find_item)->table_name; | |
| 4968 | 681 | field_name = ((Item_ident *)find_item)->field_name; | |
| 4969 | } else | ||
| 4970 | ✗ | return nullptr; | |
| 4971 | |||
| 4972 |
3/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 671 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
681 | if (db_name && lower_case_table_names) { |
| 4973 | /* Convert database to lower case for comparison */ | ||
| 4974 | ✗ | strmake(name_buff, db_name, sizeof(name_buff) - 1); | |
| 4975 | ✗ | my_casedn_str(files_charset_info, name_buff); | |
| 4976 | ✗ | db_name = name_buff; | |
| 4977 | } | ||
| 4978 | |||
| 4979 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 681 times.
|
681 | assert(field_name != nullptr); |
| 4980 | |||
| 4981 |
2/2✓ Branch 0 taken 846 times.
✓ Branch 1 taken 674 times.
|
1520 | for (ORDER *cur_group = group_list; cur_group; cur_group = cur_group->next) { |
| 4982 |
4/6✓ Branch 0 taken 846 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 846 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 646 times.
✓ Branch 5 taken 200 times.
|
846 | if ((*(cur_group->item))->real_item()->type() == Item::FIELD_ITEM) { |
| 4983 | 646 | cur_field = (Item_ident *)*cur_group->item; | |
| 4984 | 646 | cur_match_degree = 0; | |
| 4985 | |||
| 4986 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
|
646 | assert(cur_field->field_name != nullptr); |
| 4987 | |||
| 4988 |
3/4✓ Branch 0 taken 646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 267 times.
✓ Branch 3 taken 379 times.
|
646 | if (!my_strcasecmp(system_charset_info, cur_field->field_name, |
| 4989 | field_name)) | ||
| 4990 | 267 | ++cur_match_degree; | |
| 4991 | else | ||
| 4992 | 379 | continue; | |
| 4993 | |||
| 4994 |
3/4✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 219 times.
|
267 | if (cur_field->table_name && table_name) { |
| 4995 | /* If field_name is qualified by a table name. */ | ||
| 4996 |
3/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 42 times.
|
48 | if (my_strcasecmp(table_alias_charset, cur_field->table_name, |
| 4997 | table_name)) | ||
| 4998 | /* Same field names, different tables. */ | ||
| 4999 | 6 | return nullptr; | |
| 5000 | |||
| 5001 | 42 | ++cur_match_degree; | |
| 5002 |
4/4✓ Branch 0 taken 38 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 31 times.
|
42 | if (cur_field->db_name && db_name) { |
| 5003 | /* If field_name is also qualified by a database name. */ | ||
| 5004 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (strcmp(cur_field->db_name, db_name)) |
| 5005 | /* Same field names, different databases. */ | ||
| 5006 | ✗ | return nullptr; | |
| 5007 | 7 | ++cur_match_degree; | |
| 5008 | } | ||
| 5009 | } | ||
| 5010 | |||
| 5011 |
2/2✓ Branch 0 taken 260 times.
✓ Branch 1 taken 1 times.
|
261 | if (cur_match_degree > found_match_degree) { |
| 5012 | 260 | found_match_degree = cur_match_degree; | |
| 5013 | 260 | found_group = cur_group; | |
| 5014 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | } else if (found_group && (cur_match_degree == found_match_degree) && |
| 5015 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | !(*(found_group->item))->eq(cur_field, false)) { |
| 5016 | /* | ||
| 5017 | If the current resolve candidate matches equally well as the current | ||
| 5018 | best match, they must reference the same column, otherwise the field | ||
| 5019 | is ambiguous. | ||
| 5020 | */ | ||
| 5021 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_NON_UNIQ_ERROR, MYF(0), find_item->full_name(), |
| 5022 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | current_thd->where); |
| 5023 | 1 | return nullptr; | |
| 5024 | } | ||
| 5025 | } | ||
| 5026 | } | ||
| 5027 | |||
| 5028 |
2/2✓ Branch 0 taken 259 times.
✓ Branch 1 taken 415 times.
|
674 | if (found_group) |
| 5029 | 259 | return found_group->item; | |
| 5030 | else | ||
| 5031 | 415 | return nullptr; | |
| 5032 | } | ||
| 5033 | |||
| 5034 | /** | ||
| 5035 | Resolve a column reference in a sub-select. | ||
| 5036 | |||
| 5037 | Resolve a column reference (usually inside a HAVING clause) against the | ||
| 5038 | SELECT and GROUP BY clauses of the query described by 'select'. The name | ||
| 5039 | resolution algorithm searches both the SELECT and GROUP BY clauses, and in | ||
| 5040 | case of a name conflict prefers GROUP BY column names over SELECT names. If | ||
| 5041 | both clauses contain different fields with the same names, a warning is | ||
| 5042 | issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no | ||
| 5043 | GROUP BY column is found, then a HAVING name is resolved as a possibly | ||
| 5044 | derived SELECT column. | ||
| 5045 | |||
| 5046 | @param thd current thread | ||
| 5047 | @param ref column reference being resolved | ||
| 5048 | @param select the select that ref is resolved against | ||
| 5049 | |||
| 5050 | @note | ||
| 5051 | The resolution procedure is: | ||
| 5052 | - Search for a column or derived column named col_ref_i [in table T_j] | ||
| 5053 | in the SELECT clause of Q. | ||
| 5054 | - Search for a column named col_ref_i [in table T_j] | ||
| 5055 | in the GROUP BY clause of Q. | ||
| 5056 | - If found different columns with the same name in GROUP BY and SELECT, | ||
| 5057 | issue a warning | ||
| 5058 | - return the found GROUP BY column if any, | ||
| 5059 | - else return the found SELECT column if any. | ||
| 5060 | |||
| 5061 | |||
| 5062 | @return | ||
| 5063 | - NULL - there was an error, and the error was already reported | ||
| 5064 | - not_found_item - the item was not resolved, no error was reported | ||
| 5065 | - resolved item - if the item was resolved | ||
| 5066 | */ | ||
| 5067 | |||
| 5068 | 1502 | static Item **resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, | |
| 5069 | Query_block *select) { | ||
| 5070 |
1/2✓ Branch 0 taken 1502 times.
✗ Branch 1 not taken.
|
1502 | DBUG_TRACE; |
| 5071 | 1502 | Item **select_ref = nullptr; | |
| 5072 | 1502 | ORDER *group_list = select->group_list.first; | |
| 5073 | uint counter; | ||
| 5074 | enum_resolution_type resolution; | ||
| 5075 | |||
| 5076 | /* | ||
| 5077 | If a query block is a table constructor, both the SELECT list and the GROUP | ||
| 5078 | BY list don't exist. So there is no reason to search any of the lists. | ||
| 5079 | Besides, for a table constructor, we don't initialize the base_ref_items | ||
| 5080 | array until we process all the ROW() values. So we should give up if | ||
| 5081 | base_ref_items is empty. | ||
| 5082 | */ | ||
| 5083 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1502 times.
|
1502 | if (select->base_ref_items.empty()) return not_found_item; |
| 5084 | |||
| 5085 | /* | ||
| 5086 | Search for a column or derived column named as 'ref' in the SELECT | ||
| 5087 | clause of the current select. | ||
| 5088 | */ | ||
| 5089 | 1502 | if (!(select_ref = | |
| 5090 |
3/4✓ Branch 0 taken 1502 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1499 times.
|
1502 | find_item_in_list(thd, ref, select->get_fields_list(), &counter, |
| 5091 | REPORT_EXCEPT_NOT_FOUND, &resolution))) | ||
| 5092 | 3 | return nullptr; /* Some error occurred. */ | |
| 5093 |
2/2✓ Branch 0 taken 601 times.
✓ Branch 1 taken 898 times.
|
1499 | if (resolution == RESOLVED_AGAINST_ALIAS) ref->set_alias_of_expr(); |
| 5094 | |||
| 5095 | /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */ | ||
| 5096 |
7/8✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 390 times.
✓ Branch 2 taken 1109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 681 times.
✓ Branch 5 taken 428 times.
✓ Branch 6 taken 681 times.
✓ Branch 7 taken 818 times.
|
1499 | if (select->having_fix_field && !ref->has_aggregation() && group_list) { |
| 5097 |
1/2✓ Branch 0 taken 681 times.
✗ Branch 1 not taken.
|
681 | Item **group_by_ref = find_field_in_group_list(ref, group_list); |
| 5098 | |||
| 5099 | /* Check if the fields found in SELECT and GROUP BY are the same field. */ | ||
| 5100 |
6/6✓ Branch 0 taken 259 times.
✓ Branch 1 taken 422 times.
✓ Branch 2 taken 139 times.
✓ Branch 3 taken 120 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 680 times.
|
820 | if (group_by_ref && (select_ref != not_found_item) && |
| 5101 |
3/4✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 138 times.
|
139 | !((*group_by_ref)->eq(*select_ref, false))) { |
| 5102 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NON_UNIQ_ERROR, |
| 5103 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ER_THD(thd, ER_NON_UNIQ_ERROR), ref->full_name(), |
| 5104 | thd->where); | ||
| 5105 | } | ||
| 5106 | |||
| 5107 |
2/2✓ Branch 0 taken 259 times.
✓ Branch 1 taken 422 times.
|
681 | if (group_by_ref != nullptr) return group_by_ref; |
| 5108 | } | ||
| 5109 | |||
| 5110 |
2/2✓ Branch 0 taken 385 times.
✓ Branch 1 taken 855 times.
|
1240 | if (select_ref == not_found_item) return not_found_item; |
| 5111 | |||
| 5112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 855 times.
|
855 | if ((*select_ref)->has_wf()) { |
| 5113 | /* | ||
| 5114 | We can't reference an alias to a window function expr from within | ||
| 5115 | a subquery or a HAVING clause | ||
| 5116 | */ | ||
| 5117 | ✗ | my_error(ER_WINDOW_INVALID_WINDOW_FUNC_ALIAS_USE, MYF(0), ref->field_name); | |
| 5118 | ✗ | return nullptr; | |
| 5119 | } | ||
| 5120 | |||
| 5121 | /* | ||
| 5122 | The pointer in base_ref_items is nullptr if the column reference | ||
| 5123 | is a reference to itself, such as 'a' in: | ||
| 5124 | |||
| 5125 | SELECT (SELECT ... WHERE a = 1) AS a ... | ||
| 5126 | |||
| 5127 | Or if it's a reference to an expression that comes later in the | ||
| 5128 | select list, such as 'b' in: | ||
| 5129 | |||
| 5130 | SELECT (SELECT ... WHERE b = 1) AS a, (SELECT ...) AS b ... | ||
| 5131 | |||
| 5132 | Raise an error if such invalid references are encountered. | ||
| 5133 | */ | ||
| 5134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 855 times.
|
855 | if (select->base_ref_items[counter] == nullptr) { |
| 5135 | ✗ | my_error(ER_ILLEGAL_REFERENCE, MYF(0), ref->item_name.ptr(), | |
| 5136 | "forward reference in item list"); | ||
| 5137 | ✗ | return nullptr; | |
| 5138 | } | ||
| 5139 | |||
| 5140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 855 times.
|
855 | assert((*select_ref)->fixed); |
| 5141 | |||
| 5142 | 855 | return &select->base_ref_items[counter]; | |
| 5143 | 1502 | } | |
| 5144 | |||
| 5145 | /** | ||
| 5146 | Resolve the name of an outer select column reference. | ||
| 5147 | |||
| 5148 | The method resolves the column reference represented by 'this' as a column | ||
| 5149 | present in outer selects that contain current select. | ||
| 5150 | |||
| 5151 | In prepared statements, because of cache, find_field_in_tables() | ||
| 5152 | can resolve fields even if they don't belong to current context. | ||
| 5153 | In this case this method only finds appropriate context and marks | ||
| 5154 | current select as dependent. The found reference of field should be | ||
| 5155 | provided in 'from_field'. | ||
| 5156 | |||
| 5157 | @param[in] thd current thread | ||
| 5158 | @param[in,out] from_field found field reference or (Field*)not_found_field | ||
| 5159 | @param[in,out] reference view column if this item was resolved to a | ||
| 5160 | view column | ||
| 5161 | |||
| 5162 | @note | ||
| 5163 | This is the inner loop of Item_field::fix_fields: | ||
| 5164 | @code | ||
| 5165 | for each outer query Q_k beginning from the inner-most one | ||
| 5166 | { | ||
| 5167 | search for a column or derived column named col_ref_i | ||
| 5168 | [in table T_j] in the FROM clause of Q_k; | ||
| 5169 | |||
| 5170 | if such a column is not found | ||
| 5171 | Search for a column or derived column named col_ref_i | ||
| 5172 | [in table T_j] in the SELECT and GROUP clauses of Q_k. | ||
| 5173 | } | ||
| 5174 | @endcode | ||
| 5175 | |||
| 5176 | @retval | ||
| 5177 | 1 column succefully resolved and fix_fields() should continue. | ||
| 5178 | @retval | ||
| 5179 | 0 column fully fixed and fix_fields() should return false | ||
| 5180 | @retval | ||
| 5181 | -1 error occurred | ||
| 5182 | */ | ||
| 5183 | |||
| 5184 | 15219 | int Item_field::fix_outer_field(THD *thd, Field **from_field, | |
| 5185 | Item **reference) { | ||
| 5186 | 15219 | bool field_found = (*from_field != not_found_field); | |
| 5187 | 15219 | bool upward_lookup = false; | |
| 5188 | |||
| 5189 | /* | ||
| 5190 | If there are outer contexts (outer selects, but current select is | ||
| 5191 | not derived table or view) try to resolve this reference in the | ||
| 5192 | outer contexts. | ||
| 5193 | |||
| 5194 | We treat each subselect as a separate namespace, so that different | ||
| 5195 | subselects may contain columns with the same names. The subselects | ||
| 5196 | are searched starting from the innermost. | ||
| 5197 | */ | ||
| 5198 | 15219 | Name_resolution_context *last_checked_context = context; | |
| 5199 | 15219 | Item **ref = not_found_item; | |
| 5200 | 15219 | Name_resolution_context *outer_context = context->outer_context; | |
| 5201 | 15219 | Query_block *select = nullptr; | |
| 5202 | 15219 | Query_expression *cur_query_expression = nullptr; | |
| 5203 | 15219 | enum_parsing_context place = CTX_NONE; | |
| 5204 | 15219 | Query_block *cur_query_block = context->query_block; | |
| 5205 |
2/2✓ Branch 0 taken 13950 times.
✓ Branch 1 taken 1668 times.
|
15618 | for (; outer_context; outer_context = outer_context->outer_context) { |
| 5206 | 13950 | select = outer_context->query_block; | |
| 5207 | |||
| 5208 | 13950 | last_checked_context = outer_context; | |
| 5209 | 13950 | upward_lookup = true; | |
| 5210 | |||
| 5211 | /* | ||
| 5212 | We want to locate the qualifying query of our Item_field 'this'. | ||
| 5213 | 'this' is simply contained in a subquery (Query_expression) which is | ||
| 5214 | immediately contained | ||
| 5215 | - in a scalar/row subquery (Item_subselect), or | ||
| 5216 | - in a table subquery itself immediately contained in a quantified | ||
| 5217 | predicate (Item_subselect) or a derived table (TABLE_LIST). | ||
| 5218 | 'this' has an 'outer_context' where it should be searched first. | ||
| 5219 | 'outer_context' is the context of a query block or sometimes | ||
| 5220 | of a specific part of a query block (e.g. JOIN... ON condition). | ||
| 5221 | We go up from 'context' to 'outer_context', from inner to outer | ||
| 5222 | subqueries. On that bottom-up path, we stop at the subquery unit which | ||
| 5223 | is simply contained in 'outer_context': it belongs to an | ||
| 5224 | Item_subselect/TABLE_LIST object which we note OUTER_CONTEXT_OBJECT. | ||
| 5225 | Then the search of 'this' in 'outer_context' is influenced by | ||
| 5226 | where OUTER_CONTEXT_OBJECT is in 'outer_context'. For example, if | ||
| 5227 | OUTER_CONTEXT_OBJECT is in WHERE, a search by alias is not done. | ||
| 5228 | Thus, given an 'outer_context' to search in, the first step is | ||
| 5229 | to determine OUTER_CONTEXT_OBJECT. Then we search for 'this' in | ||
| 5230 | 'outer_context'. Then, if search is successful, we mark objects, from | ||
| 5231 | 'context' up to 'outer_context', as follows: | ||
| 5232 | - OUTER_CONTEXT_OBJECT is marked as "using table map this->map()"; | ||
| 5233 | - more inner subqueries are marked as "dependent on outer reference" | ||
| 5234 | (correlated, UNCACHEABLE_DEPENDENT bit) | ||
| 5235 | If search is not successful, retry with the yet-more-outer context | ||
| 5236 | (determine the new OUTER_CONTEXT_OBJECT, etc). | ||
| 5237 | |||
| 5238 | Note that any change here must be duplicated in Item_ref::fix_fields. | ||
| 5239 | */ | ||
| 5240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13950 times.
|
13950 | DBUG_PRINT("outer_field", |
| 5241 | ("must reach target ctx (having SL#%d)", select->select_number)); | ||
| 5242 | /* | ||
| 5243 | Walk from the innermost query block to the outermost until we find | ||
| 5244 | OUTER_CONTEXT_OBJECT; cur_query_block and cur_query_expression track where | ||
| 5245 | the walk currently is. | ||
| 5246 | */ | ||
| 5247 | while (true) { | ||
| 5248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14477 times.
|
14477 | if (!cur_query_block) goto loop; |
| 5249 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14477 times.
|
14477 | DBUG_PRINT("outer_field", |
| 5250 | ("in loop, in ctx of SL#%d", cur_query_block->select_number)); | ||
| 5251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14477 times.
|
14477 | assert(cur_query_block != select); |
| 5252 | 14477 | cur_query_expression = cur_query_block->master_query_expression(); | |
| 5253 |
2/2✓ Branch 0 taken 13950 times.
✓ Branch 1 taken 527 times.
|
14477 | if (cur_query_expression->outer_query_block() == select) |
| 5254 | 13950 | break; // the immediate container of cur_query_expression is | |
| 5255 | // OUTER_CONTEXT_OBJECT | ||
| 5256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 527 times.
|
527 | DBUG_PRINT("outer_field", |
| 5257 | ("in loop, in ctx of SL#%d, not yet immediate child of target", | ||
| 5258 | cur_query_block->select_number)); | ||
| 5259 | // cur_query_expression belongs to an object inside OUTER_CONTEXT_OBJECT, | ||
| 5260 | // mark it and go up: | ||
| 5261 | 527 | cur_query_expression->accumulate_used_tables(OUTER_REF_TABLE_BIT); | |
| 5262 | 527 | cur_query_block = cur_query_expression->outer_query_block(); | |
| 5263 | } | ||
| 5264 | |||
| 5265 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13950 times.
|
13950 | DBUG_PRINT("outer_field", ("out of loop, reached target ctx (having SL#%d)", |
| 5266 | cur_query_block->select_number)); | ||
| 5267 | |||
| 5268 | // Place of OUTER_CONTEXT_OBJECT in 'outer_context' e.g. WHERE : | ||
| 5269 | 13950 | place = cur_query_expression->place(); | |
| 5270 | |||
| 5271 | // A non-lateral derived table cannot see tables of its owning query | ||
| 5272 |
4/4✓ Branch 0 taken 4276 times.
✓ Branch 1 taken 9674 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 4255 times.
|
13950 | if (place == CTX_DERIVED && select->end_lateral_table == nullptr) continue; |
| 5273 | |||
| 5274 | /* | ||
| 5275 | If field was already found by first call | ||
| 5276 | to find_field_in_tables(), we only need to find appropriate context. | ||
| 5277 | */ | ||
| 5278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13929 times.
|
13929 | if (field_found && |
| 5279 | ✗ | outer_context->query_block != cached_table->query_block) { | |
| 5280 | ✗ | DBUG_PRINT("outer_field", ("but cached is of SL#%d, continue", | |
| 5281 | cached_table->query_block->select_number)); | ||
| 5282 | ✗ | continue; | |
| 5283 | } | ||
| 5284 | |||
| 5285 | /* | ||
| 5286 | In case of a view, find_field_in_tables() writes the pointer to | ||
| 5287 | the found view field into '*reference', in other words, it | ||
| 5288 | substitutes this Item_field with the found expression. | ||
| 5289 | */ | ||
| 5290 |
3/4✓ Branch 0 taken 13929 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13468 times.
✓ Branch 3 taken 461 times.
|
27858 | if (field_found || |
| 5291 | 13929 | (*from_field = find_field_in_tables( | |
| 5292 | thd, this, outer_context->first_name_resolution_table, | ||
| 5293 | outer_context->last_name_resolution_table, reference, | ||
| 5294 |
2/2✓ Branch 0 taken 13468 times.
✓ Branch 1 taken 461 times.
|
13929 | IGNORE_EXCEPT_NON_UNIQUE, thd->want_privilege, true)) != |
| 5295 | not_found_field) { | ||
| 5296 |
2/2✓ Branch 0 taken 13467 times.
✓ Branch 1 taken 1 times.
|
13468 | if (*from_field) { |
| 5297 |
2/2✓ Branch 0 taken 13411 times.
✓ Branch 1 taken 56 times.
|
13467 | if (*from_field != view_ref_found) { |
| 5298 | 13411 | cur_query_expression->accumulate_used_tables( | |
| 5299 | 13411 | (*from_field)->table->pos_in_table_list->map()); | |
| 5300 | 13411 | set_field(*from_field); | |
| 5301 | |||
| 5302 |
2/2✓ Branch 0 taken 13379 times.
✓ Branch 1 taken 32 times.
|
13411 | if (!last_checked_context->query_block->having_fix_field && |
| 5303 |
4/4✓ Branch 0 taken 189 times.
✓ Branch 1 taken 13190 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 120 times.
|
13379 | select->group_list.elements && |
| 5304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | (place == CTX_SELECT_LIST || place == CTX_HAVING)) { |
| 5305 | Item_outer_ref *rf; | ||
| 5306 | /* | ||
| 5307 | If an outer field is resolved in a grouping select then it | ||
| 5308 | is replaced for an Item_outer_ref object. Otherwise an | ||
| 5309 | Item_field object is used. | ||
| 5310 | */ | ||
| 5311 |
3/6✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 120 times.
|
120 | if (!(rf = new Item_outer_ref(context, this, select))) return -1; |
| 5312 | 120 | rf->in_sum_func = thd->lex->in_sum_func; | |
| 5313 | 120 | *reference = rf; | |
| 5314 | // WL#6570 remove-after-qa | ||
| 5315 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 116 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
120 | assert(thd->stmt_arena->is_regular() || |
| 5316 | !thd->lex->is_exec_started()); | ||
| 5317 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
|
120 | if (rf->fix_fields(thd, nullptr)) return -1; |
| 5318 | } | ||
| 5319 | /* | ||
| 5320 | A reference is resolved to a nest level that's outer or the same as | ||
| 5321 | the nest level of the enclosing set function : adjust the value of | ||
| 5322 | max_aggr_level for the function if it's needed. | ||
| 5323 | */ | ||
| 5324 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 13175 times.
|
13411 | if (thd->lex->in_sum_func && |
| 5325 | 236 | thd->lex->in_sum_func->base_query_block->nest_level >= | |
| 5326 |
1/2✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
|
236 | select->nest_level) { |
| 5327 | 236 | Item::Type ref_type = (*reference)->type(); | |
| 5328 | 236 | thd->lex->in_sum_func->max_aggr_level = | |
| 5329 | 472 | max(thd->lex->in_sum_func->max_aggr_level, | |
| 5330 | 236 | int8(select->nest_level)); | |
| 5331 | 236 | set_field(*from_field); | |
| 5332 | 236 | fixed = true; | |
| 5333 |
2/2✓ Branch 0 taken 215 times.
✓ Branch 1 taken 21 times.
|
451 | mark_as_dependent(thd, last_checked_context->query_block, |
| 5334 | 236 | context->query_block, this, | |
| 5335 |
1/2✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
|
215 | ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) |
| 5336 | ? (Item_ident *)(*reference) | ||
| 5337 | : nullptr)); | ||
| 5338 | 236 | return 0; | |
| 5339 | } | ||
| 5340 | } else { | ||
| 5341 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | Item::Type ref_type = (*reference)->type(); |
| 5342 | 56 | Used_tables ut(select); | |
| 5343 | 56 | (void)(*reference) | |
| 5344 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | ->walk(&Item::used_tables_for_level, enum_walk::SUBQUERY_POSTFIX, |
| 5345 | pointer_cast<uchar *>(&ut)); | ||
| 5346 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | cur_query_expression->accumulate_used_tables(ut.used_tables); |
| 5347 | |||
| 5348 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
|
56 | if (select->group_list.elements && place == CTX_HAVING) { |
| 5349 | /* | ||
| 5350 | If an outer field is resolved in a grouping query block then it | ||
| 5351 | is replaced with an Item_outer_ref object. Otherwise an | ||
| 5352 | Item_field object is used. | ||
| 5353 | */ | ||
| 5354 | Item_outer_ref *const rf = new Item_outer_ref( | ||
| 5355 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | context, down_cast<Item_ident *>(*reference), select); |
| 5356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (rf == nullptr) return -1; |
| 5357 | 1 | rf->in_sum_func = thd->lex->in_sum_func; | |
| 5358 | 1 | *reference = rf; | |
| 5359 | // WL#6570 remove-after-qa | ||
| 5360 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | assert(thd->stmt_arena->is_regular() || |
| 5361 | !thd->lex->is_exec_started()); | ||
| 5362 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (rf->fix_fields(thd, nullptr)) return -1; |
| 5363 | } | ||
| 5364 | |||
| 5365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | if (thd->lex->in_sum_func && |
| 5366 | ✗ | thd->lex->in_sum_func->base_query_block->nest_level >= | |
| 5367 | ✗ | select->nest_level) | |
| 5368 | ✗ | thd->lex->in_sum_func->max_aggr_level = | |
| 5369 | ✗ | max(thd->lex->in_sum_func->max_aggr_level, | |
| 5370 | ✗ | int8(select->nest_level)); | |
| 5371 | |||
| 5372 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | if ((*reference)->used_tables() != 0) |
| 5373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | mark_as_dependent(thd, last_checked_context->query_block, |
| 5374 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | context->query_block, this, |
| 5375 | ✗ | ref_type == REF_ITEM || ref_type == FIELD_ITEM | |
| 5376 | 56 | ? down_cast<Item_ident *>(*reference) | |
| 5377 | : NULL); | ||
| 5378 | /* | ||
| 5379 | A reference to a view field had been found and we | ||
| 5380 | substituted it instead of this Item (find_field_in_tables | ||
| 5381 | does it by assigning the new value to *reference), so now | ||
| 5382 | we can return from this function. | ||
| 5383 | */ | ||
| 5384 | 56 | return 0; | |
| 5385 | } | ||
| 5386 | } | ||
| 5387 | 13176 | break; | |
| 5388 | } | ||
| 5389 | |||
| 5390 | /* Search in SELECT and GROUP lists of the outer select. */ | ||
| 5391 |
4/4✓ Branch 0 taken 356 times.
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 355 times.
✓ Branch 3 taken 106 times.
|
817 | if (select_alias_referencable(place) && |
| 5392 |
2/2✓ Branch 0 taken 355 times.
✓ Branch 1 taken 1 times.
|
356 | outer_context->resolve_in_select_list) { |
| 5393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | if (!(ref = resolve_ref_in_select_and_group(thd, this, select))) |
| 5394 | ✗ | return -1; /* Some error occurred (e.g. ambiguous names). */ | |
| 5395 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 272 times.
|
355 | if (ref != not_found_item) { |
| 5396 | // The item which we found is already fixed | ||
| 5397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | assert((*ref)->fixed); |
| 5398 | 83 | cur_query_expression->accumulate_used_tables((*ref)->used_tables()); | |
| 5399 | 83 | break; | |
| 5400 | } | ||
| 5401 | } | ||
| 5402 | |||
| 5403 | /* | ||
| 5404 | Reference is not found in this select => this subquery depend on | ||
| 5405 | outer select (or we just trying to find wrong identifier, in this | ||
| 5406 | case it does not matter which used tables bits we set) | ||
| 5407 | */ | ||
| 5408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | DBUG_PRINT("outer_field", |
| 5409 | ("out of loop, reached end of big block, continue")); | ||
| 5410 | 378 | cur_query_expression->accumulate_used_tables(OUTER_REF_TABLE_BIT); | |
| 5411 | 378 | loop:; | |
| 5412 | } | ||
| 5413 | |||
| 5414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14927 times.
|
14927 | assert(ref != nullptr); |
| 5415 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14926 times.
|
14927 | if (!*from_field) return -1; |
| 5416 |
4/4✓ Branch 0 taken 14843 times.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 1668 times.
✓ Branch 3 taken 13175 times.
|
14926 | if (ref == not_found_item && *from_field == not_found_field) { |
| 5417 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1648 times.
|
1668 | if (upward_lookup) { |
| 5418 | // We can't say exactly what absent table or field | ||
| 5419 | 20 | my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where); | |
| 5420 | } else { | ||
| 5421 | /* Call find_field_in_tables only to report the error */ | ||
| 5422 | 1648 | find_field_in_tables(thd, this, context->first_name_resolution_table, | |
| 5423 | 1648 | context->last_name_resolution_table, reference, | |
| 5424 | REPORT_ALL_ERRORS, | ||
| 5425 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1648 times.
|
1648 | any_privileges ? 0 : thd->want_privilege, true); |
| 5426 | } | ||
| 5427 | 1668 | return -1; | |
| 5428 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 13175 times.
|
13258 | } else if (ref != not_found_item) { |
| 5429 | Item *save; | ||
| 5430 | Item_ref *rf; | ||
| 5431 | |||
| 5432 | /* Should have been checked in resolve_ref_in_select_and_group(). */ | ||
| 5433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | assert((*ref)->fixed); |
| 5434 | /* | ||
| 5435 | Here, a subset of actions performed by Item_ref::set_properties | ||
| 5436 | is not enough. So we pass ptr to NULL into Item_ref | ||
| 5437 | constructor, so no initialization is performed, and call | ||
| 5438 | fix_fields() below. | ||
| 5439 | */ | ||
| 5440 | 83 | save = *ref; | |
| 5441 | 83 | *ref = nullptr; // Don't call set_properties() | |
| 5442 |
4/4✓ Branch 0 taken 69 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 17 times.
|
83 | bool use_plain_ref = place == CTX_HAVING || !select->group_list.elements; |
| 5443 | 83 | rf = use_plain_ref | |
| 5444 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 17 times.
|
166 | ? new Item_ref(context, ref, db_name, table_name, field_name, |
| 5445 |
2/4✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
|
66 | m_alias_of_expr) |
| 5446 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
34 | : new Item_outer_ref(context, ref, db_name, table_name, field_name, |
| 5447 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
34 | m_alias_of_expr, select); |
| 5448 | 83 | *ref = save; | |
| 5449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | if (!rf) return -1; |
| 5450 | |||
| 5451 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 66 times.
|
83 | if (!use_plain_ref) |
| 5452 | 17 | ((Item_outer_ref *)rf)->in_sum_func = thd->lex->in_sum_func; | |
| 5453 | |||
| 5454 | 83 | *reference = rf; | |
| 5455 | // WL#6570 remove-after-qa | ||
| 5456 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
83 | assert(thd->stmt_arena->is_regular() || !thd->lex->is_exec_started()); |
| 5457 | /* | ||
| 5458 | rf is Item_ref => never substitute other items (in this case) | ||
| 5459 | during fix_fields() => we can use rf after fix_fields() | ||
| 5460 | */ | ||
| 5461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | assert(!rf->fixed); // Assured by Item_ref() |
| 5462 |
5/6✓ Branch 0 taken 46 times.
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 37 times.
✓ Branch 5 taken 46 times.
|
83 | if (rf->fix_fields(thd, reference) || rf->check_cols(1)) return -1; |
| 5463 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 10 times.
|
46 | if (rf->used_tables() != 0) |
| 5464 | 36 | mark_as_dependent(thd, last_checked_context->query_block, | |
| 5465 | 36 | context->query_block, this, rf); | |
| 5466 | 46 | return 0; | |
| 5467 | } else { | ||
| 5468 | 13175 | mark_as_dependent(thd, last_checked_context->query_block, | |
| 5469 | 13175 | context->query_block, this, (Item_ident *)*reference); | |
| 5470 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13162 times.
|
13175 | if (last_checked_context->query_block->having_fix_field) { |
| 5471 | Item_ref *rf; | ||
| 5472 | 13 | rf = new Item_ref(context, | |
| 5473 | 26 | (cached_table->db[0] ? cached_table->db : nullptr), | |
| 5474 |
3/6✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
|
13 | cached_table->alias, field_name); |
| 5475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!rf) return -1; |
| 5476 | 13 | *reference = rf; | |
| 5477 | // WL#6570 remove-after-qa | ||
| 5478 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
13 | assert(thd->stmt_arena->is_regular() || !thd->lex->is_exec_started()); |
| 5479 | /* | ||
| 5480 | rf is Item_ref => never substitute other items (in this case) | ||
| 5481 | during fix_fields() => we can use rf after fix_fields() | ||
| 5482 | */ | ||
| 5483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(!rf->fixed); // Assured by Item_ref() |
| 5484 |
5/6✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12 times.
|
13 | if (rf->fix_fields(thd, reference) || rf->check_cols(1)) return -1; |
| 5485 | 12 | return 0; | |
| 5486 | } | ||
| 5487 | } | ||
| 5488 | 13162 | return 1; | |
| 5489 | } | ||
| 5490 | |||
| 5491 | /** | ||
| 5492 | Check if the column reference that is currently being resolved, will be set | ||
| 5493 | to NULL if its qualifying query returns zero rows. | ||
| 5494 | |||
| 5495 | This is true for non-aggregated column references in the SELECT list, | ||
| 5496 | if the query block uses aggregation without grouping. For example: | ||
| 5497 | |||
| 5498 | SELECT COUNT(*), col FROM t WHERE some_condition | ||
| 5499 | |||
| 5500 | Here, if the table `t` is empty, or `some_condition` doesn't match any rows | ||
| 5501 | in `t`, the query returns one row where `col` is NULL, even if `col` is a | ||
| 5502 | not-nullable column. | ||
| 5503 | |||
| 5504 | Such column references are rejected if the ONLY_FULL_GROUP_BY SQL mode is | ||
| 5505 | enabled, in a later resolution phase. | ||
| 5506 | */ | ||
| 5507 | 82893648 | bool is_null_on_empty_table(THD *thd, Item_field *i) { | |
| 5508 | /* | ||
| 5509 | Nullability of a column item 'i' is normally determined from table's or | ||
| 5510 | view's definition. Additionally, an item may be nullable because its table | ||
| 5511 | is on the right side of a left join; but this has been handled by | ||
| 5512 | propagate_nullability() before coming here (@see TABLE::set_nullable() and | ||
| 5513 | Field::maybe_null()). | ||
| 5514 | If the table is in the left part of a left join, or is in an inner join, a | ||
| 5515 | non-nullable item may be set to NULL (table->set_null_row()) if, during | ||
| 5516 | optimization, its table is found to be empty (e.g. in read_system()) or the | ||
| 5517 | FROM clause of the qualifying query QQ of its table is found to return no | ||
| 5518 | rows. This makes a case where a non-nullable 'i' is set to NULL. Certain | ||
| 5519 | expressions containing the item, if evaluated, may find this abnormal | ||
| 5520 | behaviour. Fortunately, in the scenario described above, QQ's result is | ||
| 5521 | generally empty and so no expression is evaluated. Then we don't even | ||
| 5522 | optimize subquery expressions as their optimization may lead to evaluation | ||
| 5523 | of the item (e.g. in create_ref_for_key()). | ||
| 5524 | However there is one exception where QQ's result is not empty even though | ||
| 5525 | FROM clause's result is: when QQ is implicitly aggregated. In that case, | ||
| 5526 | return_zero_rows() sets all tables' columns to NULL and any expression in | ||
| 5527 | QQ's SELECT list is evaluated; to prepare for this, we mark the item 'i' | ||
| 5528 | as nullable below. | ||
| 5529 | - If item is not outer reference, we can reliably know if QQ is | ||
| 5530 | aggregated by testing QQ->with_sum_func | ||
| 5531 | - if it's outer reference, QQ->with_sum_func may not yet be set, e.g. if | ||
| 5532 | there is single set function referenced later in subquery and not yet | ||
| 5533 | resolved; but then context.query_block->with_sum_func is surely set (it's | ||
| 5534 | set at parsing time), so we test both members. | ||
| 5535 | - in_sum_func is the innermost set function SF containing the item; | ||
| 5536 | - if item is not an outer reference, and in_sum_func is set, SF is | ||
| 5537 | necessarily aggregated in QQ, and will not be evaluated (just be replaced | ||
| 5538 | with its "clear" value 0 or NULL), so we needn't mark 'i' as nullable; | ||
| 5539 | - if item is an outer reference and in_sum_func is set, we cannot yet know | ||
| 5540 | where SF is aggregated, it depends on other arguments of SF, so make a | ||
| 5541 | pessimistic assumption. | ||
| 5542 | Finally we test resolve_place; indeed, when QQ's result is empty, we only | ||
| 5543 | evaluate: | ||
| 5544 | - SELECT list | ||
| 5545 | - or HAVING, but columns of HAVING are always also present in SELECT list | ||
| 5546 | so are Item_ref to SELECT list and get nullability from that, | ||
| 5547 | - or ORDER BY but actually no as it's optimized away in such single-row | ||
| 5548 | query. This is not true for hypergraph optimizer. So we mark item as | ||
| 5549 | nullable if the query is ordered. For Ex: If there are window functions in | ||
| 5550 | ORDER BY, the order by list is cleared but not removed (See | ||
| 5551 | setup_order_final()). This makes hypergraph optimizer think it needs to | ||
| 5552 | execute the window function. Old optimizer does short circuiting in this | ||
| 5553 | case treating it as a constant plan. | ||
| 5554 | Note: we test with_sum_func (== references a set function); | ||
| 5555 | agg_func_used() (== is aggregation query) would be better but is not | ||
| 5556 | reliable yet at this stage. | ||
| 5557 | */ | ||
| 5558 | 82893648 | Query_block *sl = i->context->query_block; | |
| 5559 | 82893648 | Query_block *qsl = i->depended_from; | |
| 5560 | |||
| 5561 |
2/2✓ Branch 0 taken 13162 times.
✓ Branch 1 taken 82880486 times.
|
82893648 | if (qsl != nullptr) |
| 5562 | 21288 | return qsl->resolve_place == Query_block::RESOLVE_SELECT_LIST && | |
| 5563 |
6/6✓ Branch 0 taken 8126 times.
✓ Branch 1 taken 5036 times.
✓ Branch 2 taken 841 times.
✓ Branch 3 taken 7285 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 816 times.
|
20472 | (sl->with_sum_func || qsl->with_sum_func) && |
| 5564 |
2/2✓ Branch 0 taken 7264 times.
✓ Branch 1 taken 46 times.
|
20472 | qsl->group_list.elements == 0; |
| 5565 | else | ||
| 5566 | 131712459 | return (sl->resolve_place == Query_block::RESOLVE_SELECT_LIST || | |
| 5567 |
3/4✓ Branch 0 taken 67 times.
✓ Branch 1 taken 48831906 times.
✓ Branch 2 taken 424 times.
✗ Branch 3 not taken.
|
48831973 | (thd->lex->using_hypergraph_optimizer && sl->is_ordered())) && |
| 5568 |
6/6✓ Branch 0 taken 48831973 times.
✓ Branch 1 taken 34048513 times.
✓ Branch 2 taken 1047462 times.
✓ Branch 3 taken 33001476 times.
✓ Branch 4 taken 112066 times.
✓ Branch 5 taken 935396 times.
|
131824525 | sl->with_sum_func && sl->group_list.elements == 0 && |
| 5569 |
2/2✓ Branch 0 taken 139 times.
✓ Branch 1 taken 111927 times.
|
82992552 | thd->lex->in_sum_func == nullptr; |
| 5570 | } | ||
| 5571 | |||
| 5572 | /** | ||
| 5573 | Resolve the name of a column reference. | ||
| 5574 | |||
| 5575 | The method resolves the column reference represented by 'this' as a column | ||
| 5576 | present in one of: FROM clause, SELECT clause, GROUP BY clause of a query | ||
| 5577 | Q, or in outer queries that contain Q. | ||
| 5578 | |||
| 5579 | The name resolution algorithm used is (where [T_j] is an optional table | ||
| 5580 | name that qualifies the column name): | ||
| 5581 | |||
| 5582 | @code | ||
| 5583 | resolve_column_reference([T_j].col_ref_i) | ||
| 5584 | { | ||
| 5585 | search for a column or derived column named col_ref_i | ||
| 5586 | [in table T_j] in the FROM clause of Q; | ||
| 5587 | |||
| 5588 | if such a column is NOT found AND // Lookup in outer queries. | ||
| 5589 | there are outer queries | ||
| 5590 | { | ||
| 5591 | for each outer query Q_k beginning from the inner-most one | ||
| 5592 | { | ||
| 5593 | search for a column or derived column named col_ref_i | ||
| 5594 | [in table T_j] in the FROM clause of Q_k; | ||
| 5595 | |||
| 5596 | if such a column is not found | ||
| 5597 | Search for a column or derived column named col_ref_i | ||
| 5598 | [in table T_j] in the SELECT and GROUP clauses of Q_k. | ||
| 5599 | } | ||
| 5600 | } | ||
| 5601 | } | ||
| 5602 | @endcode | ||
| 5603 | |||
| 5604 | Notice that compared to Item_ref::fix_fields, here we first search the FROM | ||
| 5605 | clause, and then we search the SELECT and GROUP BY clauses. | ||
| 5606 | |||
| 5607 | For the case where a table reference is already set for the field, | ||
| 5608 | we just need to make a call to set_field(). This is true for a cloned | ||
| 5609 | field used during condition pushdown to derived tables. A cloned field | ||
| 5610 | inherits table reference, depended_from, cached_table, context and field | ||
| 5611 | from the original field. set_field() ensures all other members are set | ||
| 5612 | correctly. | ||
| 5613 | |||
| 5614 | @param[in] thd current thread | ||
| 5615 | @param[in,out] reference view column if this item was resolved to a | ||
| 5616 | view column | ||
| 5617 | |||
| 5618 | @retval | ||
| 5619 | true if error | ||
| 5620 | @retval | ||
| 5621 | false on success | ||
| 5622 | */ | ||
| 5623 | |||
| 5624 | 66948451 | bool Item_field::fix_fields(THD *thd, Item **reference) { | |
| 5625 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66948451 times.
|
66948451 | assert(fixed == 0); |
| 5626 | 66948451 | Field *from_field = not_found_field; | |
| 5627 | 66948451 | bool outer_fixed = false; | |
| 5628 | |||
| 5629 | Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler( | ||
| 5630 |
1/2✓ Branch 0 taken 66948499 times.
✗ Branch 1 not taken.
|
66948451 | thd, context->view_error_handler, context->view_error_handler_arg); |
| 5631 | |||
| 5632 |
2/2✓ Branch 0 taken 120755 times.
✓ Branch 1 taken 66827744 times.
|
66948499 | if (table_ref) { |
| 5633 | // This is a cloned field (used during condition pushdown to derived | ||
| 5634 | // tables). It has table reference and the field too. Make a call to | ||
| 5635 | // set_field() to ensure everything else gets set correctly. | ||
| 5636 | 120755 | TABLE_LIST *orig_table_ref = table_ref; | |
| 5637 |
1/2✓ Branch 0 taken 120755 times.
✗ Branch 1 not taken.
|
120755 | set_field(field); |
| 5638 | // Note that the call to set_field() above would have set the "table_ref" | ||
| 5639 | // derived from field's table which in most cases is same as the already | ||
| 5640 | // set "table_ref". However, in case of update statements, while setting | ||
| 5641 | // up update_tables, table references are changed. Since condition pushdown | ||
| 5642 | // happens after this setup, we must make sure we set the original table | ||
| 5643 | // reference for the field. | ||
| 5644 | 120755 | table_ref = orig_table_ref; | |
| 5645 | 120755 | return false; | |
| 5646 | } | ||
| 5647 |
1/2✓ Branch 0 taken 66827772 times.
✗ Branch 1 not taken.
|
66827744 | if (!field) // If field is not checked |
| 5648 | { | ||
| 5649 | /* | ||
| 5650 | In case of view, find_field_in_tables() write pointer to view field | ||
| 5651 | expression to 'reference', i.e. it substitute that expression instead | ||
| 5652 | of this Item_field | ||
| 5653 | */ | ||
| 5654 | 133655544 | from_field = find_field_in_tables( | |
| 5655 | 66827772 | thd, this, context->first_name_resolution_table, | |
| 5656 |
1/2✓ Branch 0 taken 66827762 times.
✗ Branch 1 not taken.
|
66827772 | context->last_name_resolution_table, reference, |
| 5657 |
2/2✓ Branch 0 taken 112516 times.
✓ Branch 1 taken 66715256 times.
|
66827772 | thd->lex->use_only_table_context ? REPORT_ALL_ERRORS |
| 5658 | : IGNORE_EXCEPT_NON_UNIQUE, | ||
| 5659 |
2/2✓ Branch 0 taken 382783 times.
✓ Branch 1 taken 66444989 times.
|
66827772 | any_privileges ? 0 : thd->want_privilege, true); |
| 5660 |
3/4✓ Branch 0 taken 66827894 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 66827811 times.
|
66827762 | if (thd->is_error()) goto error; |
| 5661 |
2/2✓ Branch 0 taken 15338 times.
✓ Branch 1 taken 66812473 times.
|
66827811 | if (from_field == not_found_field) { |
| 5662 | int ret; | ||
| 5663 | /* Look up in current select's item_list to find aliased fields */ | ||
| 5664 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 15091 times.
|
15338 | if (thd->lex->current_query_block()->is_item_list_lookup) { |
| 5665 | uint counter; | ||
| 5666 | enum_resolution_type resolution; | ||
| 5667 |
1/2✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
|
247 | Item **res = find_item_in_list( |
| 5668 | 247 | thd, this, &thd->lex->current_query_block()->fields, &counter, | |
| 5669 | REPORT_EXCEPT_NOT_FOUND, &resolution); | ||
| 5670 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 244 times.
|
363 | if (!res) return true; |
| 5671 |
2/2✓ Branch 0 taken 115 times.
✓ Branch 1 taken 129 times.
|
244 | if (resolution == RESOLVED_AGAINST_ALIAS) set_alias_of_expr(); |
| 5672 |
2/2✓ Branch 0 taken 116 times.
✓ Branch 1 taken 128 times.
|
244 | if (res != not_found_item) { |
| 5673 |
3/4✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 91 times.
|
116 | if ((*res)->type() == Item::FIELD_ITEM) { |
| 5674 | /* | ||
| 5675 | It's an Item_field referencing another Item_field in the select | ||
| 5676 | list. | ||
| 5677 | Use the field from the Item_field in the select list and leave | ||
| 5678 | the Item_field instance in place. | ||
| 5679 | */ | ||
| 5680 | |||
| 5681 | 25 | Item_field *const item_field = (Item_field *)(*res); | |
| 5682 | 25 | Field *const new_field = item_field->field; | |
| 5683 | |||
| 5684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (new_field == nullptr) { |
| 5685 | /* The column to which we link isn't valid. */ | ||
| 5686 | ✗ | my_error(ER_BAD_FIELD_ERROR, MYF(0), item_field->item_name.ptr(), | |
| 5687 | thd->where); | ||
| 5688 | ✗ | return true; | |
| 5689 | } | ||
| 5690 | |||
| 5691 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | set_field(new_field); |
| 5692 | |||
| 5693 | 25 | cached_table = table_ref; | |
| 5694 | |||
| 5695 | // The found column may be an outer reference | ||
| 5696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (item_field->depended_from) |
| 5697 | ✗ | mark_as_dependent(thd, item_field->depended_from, | |
| 5698 | ✗ | context->query_block, this, this); | |
| 5699 | |||
| 5700 | 25 | return false; | |
| 5701 | } else { | ||
| 5702 | /* | ||
| 5703 | It's not an Item_field in the select list so we must make a new | ||
| 5704 | Item_ref to point to the Item in the select list and replace the | ||
| 5705 | Item_field created by the parser with the new Item_ref. | ||
| 5706 | Ex: SELECT func1(col) as c ... ORDER BY func2(c); | ||
| 5707 | NOTE: If we are fixing an alias reference inside ORDER/GROUP BY | ||
| 5708 | item tree, then we use new Item_ref as an | ||
| 5709 | intermediate value to resolve referenced item only. | ||
| 5710 | In this case the new Item_ref item is unused. | ||
| 5711 | */ | ||
| 5712 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 1 times.
|
91 | if (resolution == RESOLVED_AGAINST_ALIAS) |
| 5713 | 90 | res = &thd->lex->current_query_block()->base_ref_items[counter]; | |
| 5714 | |||
| 5715 | Item_ref *rf = | ||
| 5716 | new Item_ref(context, res, db_name, table_name, field_name, | ||
| 5717 |
2/4✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
|
91 | resolution == RESOLVED_AGAINST_ALIAS); |
| 5718 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
|
91 | if (rf == nullptr) return true; |
| 5719 | |||
| 5720 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
|
91 | if (!rf->fixed) { |
| 5721 | // No need for recursive resolving of aliases. | ||
| 5722 | const bool group_fix_field = | ||
| 5723 | ✗ | thd->lex->current_query_block()->group_fix_field; | |
| 5724 | ✗ | thd->lex->current_query_block()->group_fix_field = false; | |
| 5725 | bool fix_error = | ||
| 5726 | ✗ | rf->fix_fields(thd, (Item **)&rf) || rf->check_cols(1); | |
| 5727 | ✗ | thd->lex->current_query_block()->group_fix_field = | |
| 5728 | group_fix_field; | ||
| 5729 | ✗ | if (fix_error) return true; | |
| 5730 | } | ||
| 5731 | 91 | *reference = rf; | |
| 5732 | // WL#6570 remove-after-qa | ||
| 5733 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
91 | assert(thd->stmt_arena->is_regular() || |
| 5734 | !thd->lex->is_exec_started()); | ||
| 5735 | |||
| 5736 | 91 | return false; | |
| 5737 | } | ||
| 5738 | } | ||
| 5739 | } | ||
| 5740 |
3/4✓ Branch 0 taken 15219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1707 times.
✓ Branch 3 taken 13512 times.
|
15219 | if ((ret = fix_outer_field(thd, &from_field, reference)) < 0) goto error; |
| 5741 | 13512 | outer_fixed = true; | |
| 5742 |
2/2✓ Branch 0 taken 350 times.
✓ Branch 1 taken 13162 times.
|
13512 | if (!ret) return false; |
| 5743 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 66812467 times.
|
66812473 | } else if (!from_field) |
| 5744 | 6 | goto error; | |
| 5745 | |||
| 5746 | /* | ||
| 5747 | We should resolve this as an outer field reference if | ||
| 5748 | 1. we haven't done it before, and | ||
| 5749 | 2. the query_block of the table that contains this field is | ||
| 5750 | different from the query_block of the current name resolution | ||
| 5751 | context. | ||
| 5752 | */ | ||
| 5753 |
2/2✓ Branch 0 taken 66812369 times.
✓ Branch 1 taken 13260 times.
|
66825629 | if (!outer_fixed && // 1 |
| 5754 |
3/4✓ Branch 0 taken 66699800 times.
✓ Branch 1 taken 112569 times.
✓ Branch 2 taken 66699814 times.
✗ Branch 3 not taken.
|
66812369 | cached_table && cached_table->query_block && |
| 5755 |
1/2✓ Branch 0 taken 66699837 times.
✗ Branch 1 not taken.
|
66699814 | context->query_block && // 2 |
| 5756 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66699837 times.
|
66699837 | cached_table->query_block != context->query_block) { |
| 5757 | int ret; | ||
| 5758 | ✗ | if ((ret = fix_outer_field(thd, &from_field, reference)) < 0) goto error; | |
| 5759 | ✗ | outer_fixed = true; | |
| 5760 | ✗ | if (!ret) return false; | |
| 5761 | } | ||
| 5762 | |||
| 5763 | /* | ||
| 5764 | If inside an aggregation function, set the correct aggregation level. | ||
| 5765 | Even if a view reference is found, the level is still the query block | ||
| 5766 | associated with the context of the current item: | ||
| 5767 | */ | ||
| 5768 |
4/6✓ Branch 0 taken 3047218 times.
✓ Branch 1 taken 63778411 times.
✓ Branch 2 taken 3047218 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3047218 times.
|
66825629 | assert(from_field != view_ref_found || |
| 5769 | context->query_block == | ||
| 5770 | dynamic_cast<Item_ident *>(*reference)->context->query_block); | ||
| 5771 |
2/2✓ Branch 0 taken 824403 times.
✓ Branch 1 taken 66001226 times.
|
66825629 | if (thd->lex->in_sum_func && |
| 5772 | 824403 | thd->lex->in_sum_func->base_query_block->nest_level == | |
| 5773 |
2/2✓ Branch 0 taken 824326 times.
✓ Branch 1 taken 77 times.
|
824403 | context->query_block->nest_level) |
| 5774 | 824326 | thd->lex->in_sum_func->max_aggr_level = | |
| 5775 | 1648652 | max(thd->lex->in_sum_func->max_aggr_level, | |
| 5776 | 824326 | int8(context->query_block->nest_level)); | |
| 5777 | |||
| 5778 | // If view column reference, Item in *reference is completely resolved: | ||
| 5779 |
2/2✓ Branch 0 taken 3047218 times.
✓ Branch 1 taken 63778411 times.
|
66825629 | if (from_field == view_ref_found) { |
| 5780 |
3/4✓ Branch 0 taken 3047218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 3047197 times.
|
3047218 | if (is_null_on_empty_table(thd, this)) { |
| 5781 | 21 | (*reference)->set_nullable(true); | |
| 5782 |
4/6✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 1 times.
|
21 | if ((*reference)->real_item()->type() == Item::FIELD_ITEM) { |
| 5783 | // See below for explanation. | ||
| 5784 | TABLE *table = | ||
| 5785 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | down_cast<Item_field *>((*reference)->real_item())->field->table; |
| 5786 | 20 | table->set_nullable(); | |
| 5787 | } | ||
| 5788 | } | ||
| 5789 | 3047218 | return false; | |
| 5790 | } | ||
| 5791 | |||
| 5792 |
3/4✓ Branch 0 taken 63778424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 63778422 times.
|
63778411 | if (from_field->is_hidden_by_system()) { |
| 5793 | /* | ||
| 5794 | This field is either hidden by the storage engine or SQL layer. In | ||
| 5795 | either case, report column "not found" error. | ||
| 5796 | */ | ||
| 5797 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_BAD_FIELD_ERROR, MYF(0), from_field->field_name, thd->where); |
| 5798 | 2 | return true; | |
| 5799 | } | ||
| 5800 | |||
| 5801 | // Not view reference, not outer reference; need to set properties: | ||
| 5802 |
1/2✓ Branch 0 taken 63778159 times.
✗ Branch 1 not taken.
|
63778422 | set_field(from_field); |
| 5803 | ✗ | } else if (thd->mark_used_columns != MARK_COLUMNS_NONE) { | |
| 5804 | ✗ | TABLE *table = field->table; | |
| 5805 | MY_BITMAP *current_bitmap; | ||
| 5806 | MY_BITMAP *other_bitmap [[maybe_unused]]; | ||
| 5807 | ✗ | if (thd->mark_used_columns == MARK_COLUMNS_READ) { | |
| 5808 | ✗ | current_bitmap = table->read_set; | |
| 5809 | ✗ | other_bitmap = table->write_set; | |
| 5810 | } else { | ||
| 5811 | ✗ | current_bitmap = table->write_set; | |
| 5812 | ✗ | other_bitmap = table->read_set; | |
| 5813 | } | ||
| 5814 | ✗ | if (!bitmap_test_and_set(current_bitmap, field->field_index())) | |
| 5815 | ✗ | assert(bitmap_is_set(other_bitmap, field->field_index())); | |
| 5816 | } | ||
| 5817 |
2/2✓ Branch 0 taken 371143 times.
✓ Branch 1 taken 63406988 times.
|
63778131 | if (any_privileges) { |
| 5818 | const char *db, *tab; | ||
| 5819 | 371143 | db = cached_table->get_db_name(); | |
| 5820 | 371143 | tab = cached_table->get_table_name(); | |
| 5821 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 371143 times.
|
371143 | assert(field->table == table_ref->table); |
| 5822 | 371143 | if (!(have_privileges = | |
| 5823 |
2/4✓ Branch 0 taken 371143 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 371143 times.
|
371143 | (get_column_grant(thd, &table_ref->grant, db, tab, field_name) & |
| 5824 | VIEW_ANY_ACL))) { | ||
| 5825 | ✗ | my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY", | |
| 5826 | ✗ | thd->security_context()->priv_user().str, | |
| 5827 | ✗ | thd->security_context()->host_or_ip().str, field_name, tab); | |
| 5828 | ✗ | goto error; | |
| 5829 | } | ||
| 5830 | } | ||
| 5831 | 63778131 | fixed = true; | |
| 5832 |
3/4✓ Branch 0 taken 63778253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7382 times.
✓ Branch 3 taken 63770871 times.
|
63778131 | if (is_null_on_empty_table(thd, this)) { |
| 5833 | 7382 | set_nullable(true); | |
| 5834 | |||
| 5835 | // The Item is now nullable, but the underlying field still isn't, | ||
| 5836 | // and Copy_field uses the underlying field. Thus, | ||
| 5837 | // ZeroRowsAggregatedIterator sets the _table_ row to NULL instead, and | ||
| 5838 | // thus, it needs to be nullable. This is similar to how inner tables of | ||
| 5839 | // outer joins need to be nullable. | ||
| 5840 | 7382 | field->table->set_nullable(); | |
| 5841 | } | ||
| 5842 | 63778298 | return false; | |
| 5843 | |||
| 5844 | 1796 | error: | |
| 5845 | 1796 | return true; | |
| 5846 | 66948538 | } | |
| 5847 | |||
| 5848 | 22445531 | void Item_field::bind_fields() { | |
| 5849 |
2/2✓ Branch 0 taken 222588 times.
✓ Branch 1 taken 22222943 times.
|
22445531 | if (!fixed) return; |
| 5850 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22222943 times.
|
22222943 | assert(field_index != NO_FIELD_INDEX); |
| 5851 | /* | ||
| 5852 | Check consistency of Item_field objects: | ||
| 5853 | - If we have no table_ref, then field must be a valid pointer. | ||
| 5854 | (Applicable for expressions of generated columns). | ||
| 5855 | - Some temporary tables used for materialization (derived tables) | ||
| 5856 | have permanent metadata, hence both table_ref and field are valid. | ||
| 5857 | - All other tables that have a valid table_ref do not have a valid | ||
| 5858 | field reference at this point. | ||
| 5859 | */ | ||
| 5860 |
14/20✓ Branch 0 taken 36795 times.
✓ Branch 1 taken 22186148 times.
✓ Branch 2 taken 36795 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22186886 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22150582 times.
✓ Branch 7 taken 36090 times.
✓ Branch 8 taken 293 times.
✓ Branch 9 taken 22150451 times.
✓ Branch 10 taken 36383 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 22150609 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 22150593 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 22150657 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 22150629 times.
✓ Branch 19 taken 28 times.
|
22222943 | assert((table_ref == nullptr && field != nullptr) || |
| 5861 | (table_ref != nullptr && | ||
| 5862 | (table_ref->is_view_or_derived() || | ||
| 5863 | table_ref->is_recursive_reference()) && | ||
| 5864 | field != nullptr) || | ||
| 5865 | (table_ref != nullptr && | ||
| 5866 | !(table_ref->is_view_or_derived() || | ||
| 5867 | table_ref->is_recursive_reference()) && | ||
| 5868 | field == nullptr)); | ||
| 5869 |
3/4✓ Branch 0 taken 22187092 times.
✓ Branch 1 taken 36715 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22187092 times.
|
22223807 | if (table_ref != nullptr && table_ref->table == nullptr) return; |
| 5870 |
2/2✓ Branch 0 taken 22150746 times.
✓ Branch 1 taken 73061 times.
|
22223807 | if (field == nullptr) { |
| 5871 | 22150746 | field = result_field = table_ref->table->field[field_index]; | |
| 5872 | 22150746 | m_orig_field_name = field->field_name; | |
| 5873 | } | ||
| 5874 |
2/2✓ Branch 0 taken 36240 times.
✓ Branch 1 taken 22187567 times.
|
22223807 | if (table_name == nullptr) table_name = *field->table_name; |
| 5875 | } | ||
| 5876 | |||
| 5877 | 11097 | Item *Item_field::safe_charset_converter(THD *thd, const CHARSET_INFO *tocs) { | |
| 5878 | 11097 | no_constant_propagation = true; | |
| 5879 | 11097 | return Item::safe_charset_converter(thd, tocs); | |
| 5880 | } | ||
| 5881 | |||
| 5882 | 114223263 | void Item_field::cleanup() { | |
| 5883 |
1/2✓ Branch 0 taken 114225570 times.
✗ Branch 1 not taken.
|
114223263 | DBUG_TRACE; |
| 5884 |
2/2✓ Branch 0 taken 5205781 times.
✓ Branch 1 taken 109019789 times.
|
114225570 | if (!fixed) return; |
| 5885 | |||
| 5886 | 109019789 | Item_ident::cleanup(); | |
| 5887 | /* | ||
| 5888 | When TABLE is detached from TABLE_LIST, field pointers are invalid, | ||
| 5889 | unless field objects are created as part of statement (placeholder tables). | ||
| 5890 | Also invalidate the original field name, since it is usually determined | ||
| 5891 | from the field name in the Field object. | ||
| 5892 | */ | ||
| 5893 |
6/6✓ Branch 0 taken 103468962 times.
✓ Branch 1 taken 5550185 times.
✓ Branch 2 taken 102589826 times.
✓ Branch 3 taken 879069 times.
✓ Branch 4 taken 102552502 times.
✓ Branch 5 taken 6467255 times.
|
211609650 | if (table_ref != nullptr && !table_ref->is_view_or_derived() && |
| 5894 |
2/2✓ Branch 0 taken 102552574 times.
✓ Branch 1 taken 37929 times.
|
102589826 | !table_ref->is_recursive_reference()) { |
| 5895 | 102552502 | field = nullptr; | |
| 5896 | 102552502 | m_orig_field_name = nullptr; | |
| 5897 | } | ||
| 5898 | |||
| 5899 | // Restore result field back to the initial value | ||
| 5900 | 109019757 | result_field = field; | |
| 5901 | |||
| 5902 | /* | ||
| 5903 | When table_ref is NULL, table_name must be reassigned together with | ||
| 5904 | table pointer. | ||
| 5905 | */ | ||
| 5906 |
2/2✓ Branch 0 taken 5550705 times.
✓ Branch 1 taken 103469052 times.
|
109019757 | if (table_ref == nullptr) table_name = nullptr; |
| 5907 | |||
| 5908 | // Reset field before next optimization (multiple equality analysis) | ||
| 5909 | 109019757 | item_equal = nullptr; | |
| 5910 | 109019757 | item_equal_all_join_nests = nullptr; | |
| 5911 | 109019757 | null_value = false; | |
| 5912 |
2/2✓ Branch 0 taken 109019943 times.
✓ Branch 1 taken 5205743 times.
|
114225538 | } |
| 5913 | |||
| 5914 | /** | ||
| 5915 | Reset all aspect of a field object, so that it can be re-resolved. | ||
| 5916 | This is only for use in prepared CREATE TABLE statements. | ||
| 5917 | @todo refactor CREATE TABLE so this is no longer needed. | ||
| 5918 | */ | ||
| 5919 | 2585 | void Item_field::reset_field() { | |
| 5920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2585 times.
|
2585 | assert(table_ref == nullptr); |
| 5921 | 2585 | fixed = false; | |
| 5922 | 2585 | context = nullptr; | |
| 5923 | 2585 | db_name = m_orig_db_name; | |
| 5924 | 2585 | table_name = m_orig_table_name; | |
| 5925 | 2585 | m_orig_field_name = field_name; | |
| 5926 | 2585 | field = nullptr; | |
| 5927 | 2585 | } | |
| 5928 | |||
| 5929 | /** | ||
| 5930 | Find a field among specified multiple equalities. | ||
| 5931 | |||
| 5932 | The function first searches the field among multiple equalities | ||
| 5933 | of the current level (in the cond_equal->current_level list). | ||
| 5934 | If it fails, it continues searching in upper levels accessed | ||
| 5935 | through a pointer cond_equal->upper_levels. | ||
| 5936 | The search terminates as soon as a multiple equality containing | ||
| 5937 | the field is found. | ||
| 5938 | |||
| 5939 | @param cond_equal reference to list of multiple equalities where | ||
| 5940 | the field (this object) is to be looked for | ||
| 5941 | |||
| 5942 | @return | ||
| 5943 | - First Item_equal containing the field, if success | ||
| 5944 | - nullptr, otherwise | ||
| 5945 | */ | ||
| 5946 | |||
| 5947 | 6111284 | Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) const { | |
| 5948 |
2/2✓ Branch 0 taken 1078971 times.
✓ Branch 1 taken 5990964 times.
|
7069935 | while (cond_equal) { |
| 5949 |
5/8✓ Branch 0 taken 1078965 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1078972 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3195351 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2236700 times.
✓ Branch 7 taken 958651 times.
|
3195324 | for (Item_equal &item : cond_equal->current_level) { |
| 5950 |
3/4✓ Branch 0 taken 2236674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120321 times.
✓ Branch 3 taken 2116353 times.
|
2236698 | if (item.contains(field)) return &item; |
| 5951 | } | ||
| 5952 | /* | ||
| 5953 | The field is not found in any of the multiple equalities | ||
| 5954 | of the current level. Look for it in upper levels | ||
| 5955 | */ | ||
| 5956 | 958651 | cond_equal = cond_equal->upper_levels; | |
| 5957 | } | ||
| 5958 | 5990964 | return nullptr; | |
| 5959 | } | ||
| 5960 | |||
| 5961 | /** | ||
| 5962 | Check whether a field can be substituted by an equal item. | ||
| 5963 | |||
| 5964 | The function checks whether a substitution of the field | ||
| 5965 | occurrence for an equal item is valid. | ||
| 5966 | |||
| 5967 | @param arg *arg != NULL <-> the field is in the context where | ||
| 5968 | substitution for an equal item is valid | ||
| 5969 | |||
| 5970 | @note | ||
| 5971 | The following statement is not always true: | ||
| 5972 | @n | ||
| 5973 | x=y => F(x)=F(x/y). | ||
| 5974 | @n | ||
| 5975 | This means substitution of an item for an equal item not always | ||
| 5976 | yields an equavalent condition. Here's an example: | ||
| 5977 | @code | ||
| 5978 | 'a'='a ' | ||
| 5979 | (LENGTH('a')=1) != (LENGTH('a ')=2) | ||
| 5980 | @endcode | ||
| 5981 | Such a substitution is surely valid if either the substituted | ||
| 5982 | field is not of a STRING type or if it is an argument of | ||
| 5983 | a comparison predicate. | ||
| 5984 | |||
| 5985 | @retval | ||
| 5986 | true substitution is valid | ||
| 5987 | @retval | ||
| 5988 | false otherwise | ||
| 5989 | */ | ||
| 5990 | |||
| 5991 | 2589460 | bool Item_field::subst_argument_checker(uchar **arg) { | |
| 5992 |
4/4✓ Branch 0 taken 2489942 times.
✓ Branch 1 taken 99531 times.
✓ Branch 2 taken 513433 times.
✓ Branch 3 taken 1976509 times.
|
2589460 | return (result_type() != STRING_RESULT) || (*arg); |
| 5993 | } | ||
| 5994 | |||
| 5995 | /** | ||
| 5996 | Convert a numeric value to a zero-filled string | ||
| 5997 | |||
| 5998 | @param[in,out] item the item to operate on | ||
| 5999 | @param field The field that this value is equated to | ||
| 6000 | |||
| 6001 | This function converts a numeric value to a string. In this conversion | ||
| 6002 | the zero-fill flag of the field is taken into account. | ||
| 6003 | This is required so the resulting string value can be used instead of | ||
| 6004 | the field reference when propagating equalities. | ||
| 6005 | */ | ||
| 6006 | |||
| 6007 | 5 | static void convert_zerofill_number_to_string(Item **item, | |
| 6008 | const Field_num *field) { | ||
| 6009 | char buff[MAX_FIELD_WIDTH], *pos; | ||
| 6010 | 5 | String tmp(buff, sizeof(buff), field->charset()), *res; | |
| 6011 | |||
| 6012 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | res = (*item)->val_str(&tmp); |
| 6013 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
|
5 | if ((*item)->null_value) |
| 6014 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | *item = new Item_null(); |
| 6015 | else { | ||
| 6016 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | field->prepend_zeros(res); |
| 6017 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | pos = sql_strmake(res->ptr(), res->length()); |
| 6018 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *item = new Item_string(pos, res->length(), field->charset()); |
| 6019 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (*item == nullptr) return; |
| 6020 | // Ensure the string has same properties as a number | ||
| 6021 | 4 | (*item)->collation.derivation = DERIVATION_NUMERIC; | |
| 6022 | } | ||
| 6023 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | } |
| 6024 | |||
| 6025 | /** | ||
| 6026 | Set a pointer to the multiple equality the field reference belongs to | ||
| 6027 | (if any). | ||
| 6028 | |||
| 6029 | The function looks for a multiple equality containing the field item | ||
| 6030 | among those referenced by arg. | ||
| 6031 | In the case such equality exists the function does the following. | ||
| 6032 | If the found multiple equality contains a constant, then the field | ||
| 6033 | reference is substituted for this constant, otherwise it sets a pointer | ||
| 6034 | to the multiple equality in the field item. | ||
| 6035 | |||
| 6036 | |||
| 6037 | @param arg reference to list of multiple equalities where | ||
| 6038 | the field (this object) is to be looked for | ||
| 6039 | |||
| 6040 | @note | ||
| 6041 | This function is supposed to be called as a callback parameter in calls | ||
| 6042 | of the compile method. | ||
| 6043 | |||
| 6044 | @return | ||
| 6045 | - pointer to the replacing constant item, if the field item was substituted | ||
| 6046 | - pointer to the field item, otherwise. | ||
| 6047 | */ | ||
| 6048 | |||
| 6049 | 612967 | Item *Item_field::equal_fields_propagator(uchar *arg) { | |
| 6050 |
2/2✓ Branch 0 taken 21016 times.
✓ Branch 1 taken 591951 times.
|
612967 | if (no_constant_propagation) return this; |
| 6051 |
1/2✓ Branch 0 taken 591952 times.
✗ Branch 1 not taken.
|
591951 | item_equal = find_item_equal((COND_EQUAL *)arg); |
| 6052 | 591952 | Item *item = nullptr; | |
| 6053 |
2/2✓ Branch 0 taken 5039 times.
✓ Branch 1 taken 586913 times.
|
591952 | if (item_equal) item = item_equal->get_const(); |
| 6054 | /* | ||
| 6055 | Disable const propagation for items used in different comparison contexts. | ||
| 6056 | This must be done because, for example, Item_hex_string->val_int() is not | ||
| 6057 | the same as (Item_hex_string->val_str() in BINARY column)->val_int(). | ||
| 6058 | We cannot simply disable the replacement in a particular context ( | ||
| 6059 | e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since | ||
| 6060 | Items don't know the context they are in and there are functions like | ||
| 6061 | IF (<hex_string>, 'yes', 'no'). | ||
| 6062 | |||
| 6063 | Also, disable const propagation if the constant is nullable and this item is | ||
| 6064 | not. If we were to allow propagation in this case, we would also need to | ||
| 6065 | propagate the new nullability up to the parents of this item. | ||
| 6066 | */ | ||
| 6067 |
8/8✓ Branch 0 taken 1707 times.
✓ Branch 1 taken 590245 times.
✓ Branch 2 taken 1681 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 1631 times.
✓ Branch 6 taken 590314 times.
✓ Branch 7 taken 1637 times.
|
593682 | if (item == nullptr || !has_compatible_context(item) || |
| 6068 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 6 times.
|
1731 | (item->is_nullable() && !is_nullable())) |
| 6069 | 590314 | item = this; | |
| 6070 |
5/6✓ Branch 0 taken 1637 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✓ Branch 3 taken 1375 times.
✓ Branch 4 taken 262 times.
✓ Branch 5 taken 1375 times.
|
1899 | else if (field && field->is_flag_set(ZEROFILL_FLAG) && |
| 6071 |
7/16✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 261 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 261 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
262 | IS_NUM(field->type())) { |
| 6072 | /* | ||
| 6073 | We don't need to zero-fill timestamp columns here because they will be | ||
| 6074 | first converted to a string (in date/time format) and compared as such if | ||
| 6075 | compared with another string. | ||
| 6076 | */ | ||
| 6077 |
2/4✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
|
262 | if (item && field->type() != FIELD_TYPE_TIMESTAMP && |
| 6078 |
5/6✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 257 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 257 times.
|
529 | cmp_context != INT_RESULT && |
| 6079 |
3/6✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | item->real_item()->type() != Item::REAL_ITEM) |
| 6080 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | convert_zerofill_number_to_string(&item, (Field_num *)field); |
| 6081 | else | ||
| 6082 | 257 | item = this; | |
| 6083 | } | ||
| 6084 | 591951 | return item; | |
| 6085 | } | ||
| 6086 | |||
| 6087 | /** | ||
| 6088 | If this field is the target is the target of replacement, replace it with | ||
| 6089 | the info object's item or, if the item is found inside a subquery, the target | ||
| 6090 | is an outer reference, so we create a new Item_field, mark it accordingly | ||
| 6091 | and replace with that instead. | ||
| 6092 | |||
| 6093 | @param arg An info object of type Item::Item_field_replacement. | ||
| 6094 | @returns the resulting item, replaced or not, or nullptr if error | ||
| 6095 | */ | ||
| 6096 | ✗ | Item *Item_field::replace_item_field(uchar *arg) { | |
| 6097 | ✗ | auto *info = pointer_cast<Item::Item_field_replacement *>(arg); | |
| 6098 | |||
| 6099 | ✗ | if (field == info->m_target) { | |
| 6100 | ✗ | if (info->m_curr_block == info->m_trans_block) return info->m_item; | |
| 6101 | |||
| 6102 | // The field is an outer reference, so we cannot reuse transformed query | ||
| 6103 | // block's Item_field; make a new one for this query block | ||
| 6104 | ✗ | THD *const thd = current_thd; | |
| 6105 | ✗ | Item_field *outer_field = new (thd->mem_root) Item_field(thd, info->m_item); | |
| 6106 | ✗ | if (outer_field == nullptr) return nullptr; /* purecov: inspected */ | |
| 6107 | ✗ | outer_field->depended_from = info->m_trans_block; | |
| 6108 | ✗ | outer_field->context = &info->m_curr_block->context; | |
| 6109 | ✗ | return outer_field; | |
| 6110 | } | ||
| 6111 | |||
| 6112 | ✗ | return this; | |
| 6113 | } | ||
| 6114 | |||
| 6115 | /** | ||
| 6116 | Replace an Item_field for an equal Item_field that evaluated earlier | ||
| 6117 | (if any). | ||
| 6118 | |||
| 6119 | The function returns a pointer to an item that is taken from | ||
| 6120 | the very beginning of the item_equal list which the Item_field | ||
| 6121 | object refers to (belongs to) unless item_equal contains a constant | ||
| 6122 | item. In this case the function returns this constant item, | ||
| 6123 | (if the substitution does not require conversion). | ||
| 6124 | If the Item_field object does not refer any Item_equal object | ||
| 6125 | 'this' is returned . | ||
| 6126 | |||
| 6127 | @note | ||
| 6128 | This function is supposed to be called as a callback parameter in calls | ||
| 6129 | of the thransformer method. | ||
| 6130 | |||
| 6131 | @return | ||
| 6132 | - pointer to a replacement Item_field if there is a better equal item or | ||
| 6133 | a pointer to a constant equal item; | ||
| 6134 | - this - otherwise. | ||
| 6135 | */ | ||
| 6136 | |||
| 6137 | 2863056 | Item *Item_field::replace_equal_field(uchar *) { | |
| 6138 |
2/2✓ Branch 0 taken 3588 times.
✓ Branch 1 taken 2859468 times.
|
2863056 | if (item_equal) { |
| 6139 | 3588 | Item *const_item = item_equal->get_const(); | |
| 6140 |
2/2✓ Branch 0 taken 346 times.
✓ Branch 1 taken 3242 times.
|
3588 | if (const_item) { |
| 6141 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 320 times.
|
346 | if (!has_compatible_context(const_item)) return this; |
| 6142 | 320 | return const_item; | |
| 6143 | } | ||
| 6144 | 3242 | Item_field *subst = item_equal->get_subst_item(this); | |
| 6145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3242 times.
|
3242 | assert(subst); |
| 6146 |
3/4✓ Branch 0 taken 992 times.
✓ Branch 1 taken 2250 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 992 times.
|
3242 | assert(table_ref == subst->table_ref || |
| 6147 | table_ref->table != subst->table_ref->table); | ||
| 6148 |
5/6✓ Branch 0 taken 992 times.
✓ Branch 1 taken 2250 times.
✓ Branch 2 taken 992 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 992 times.
✓ Branch 5 taken 2250 times.
|
3242 | if (table_ref != subst->table_ref && !field->eq(subst->field)) { |
| 6149 | // We may have to undo the substitution that is done here when setting up | ||
| 6150 | // hash join; the new field may be a field from a table that is not | ||
| 6151 | // reachable from hash join. Store which multi-equality we found the field | ||
| 6152 | // substitution in, so that we can go back and find a field that the hash | ||
| 6153 | // join can reach. | ||
| 6154 | 992 | subst->set_item_equal_all_join_nests(item_equal); | |
| 6155 | 992 | return subst; | |
| 6156 | } | ||
| 6157 | } | ||
| 6158 | 2861718 | return this; | |
| 6159 | } | ||
| 6160 | |||
| 6161 | 22127405 | void Item::init_make_field(Send_field *tmp_field, | |
| 6162 | enum enum_field_types field_type_arg) { | ||
| 6163 | 22127405 | const char *empty_name = ""; | |
| 6164 | 22127405 | tmp_field->db_name = empty_name; | |
| 6165 | 22127405 | tmp_field->org_table_name = empty_name; | |
| 6166 | 22127405 | tmp_field->org_col_name = empty_name; | |
| 6167 | 22127405 | tmp_field->table_name = empty_name; | |
| 6168 | 22127405 | tmp_field->col_name = item_name.ptr(); | |
| 6169 | 22127410 | tmp_field->charsetnr = collation.collation->number; | |
| 6170 | 22127405 | tmp_field->flags = | |
| 6171 |
2/2✓ Branch 0 taken 8007531 times.
✓ Branch 1 taken 14119879 times.
|
22127410 | (m_nullable ? 0 : NOT_NULL_FLAG) | |
| 6172 |
2/2✓ Branch 0 taken 5732026 times.
✓ Branch 1 taken 16395379 times.
|
22127410 | (my_binary_compare(charset_for_protocol()) ? BINARY_FLAG : 0); |
| 6173 | 22127405 | tmp_field->type = field_type_arg; | |
| 6174 | 22127405 | tmp_field->length = max_length; | |
| 6175 | 22127405 | tmp_field->decimals = decimals; | |
| 6176 |
2/2✓ Branch 0 taken 3874173 times.
✓ Branch 1 taken 18253232 times.
|
22127405 | if (unsigned_flag) tmp_field->flags |= UNSIGNED_FLAG; |
| 6177 | 22127405 | tmp_field->field = false; | |
| 6178 | 22127405 | } | |
| 6179 | |||
| 6180 | 12907279 | void Item::make_field(Send_field *tmp_field) { | |
| 6181 | 12907279 | init_make_field(tmp_field, data_type()); | |
| 6182 | 12907284 | } | |
| 6183 | |||
| 6184 | 9220127 | void Item_empty_string::make_field(Send_field *tmp_field) { | |
| 6185 | 9220127 | init_make_field(tmp_field, string_field_type(max_length)); | |
| 6186 | 9220128 | } | |
| 6187 | |||
| 6188 | /** | ||
| 6189 | Verifies that the input string is well-formed according to its character set. | ||
| 6190 | @param str input string to verify | ||
| 6191 | @param send_error If true, call my_error if string is not well-formed. | ||
| 6192 | @param truncate If true, set to null/truncate if not well-formed. | ||
| 6193 | |||
| 6194 | @return | ||
| 6195 | If well-formed: input string. | ||
| 6196 | If not well-formed: | ||
| 6197 | if truncate is true and strict mode: NULL pointer and we set this | ||
| 6198 | Item's value to NULL. | ||
| 6199 | if truncate is true and not strict mode: input string truncated up to | ||
| 6200 | last good character. | ||
| 6201 | if truncate is false: input string is returned. | ||
| 6202 | */ | ||
| 6203 | 50134727 | String *Item::check_well_formed_result(String *str, bool send_error, | |
| 6204 | bool truncate) { | ||
| 6205 | /* Check whether we got a well-formed string */ | ||
| 6206 | 50134727 | const CHARSET_INFO *cs = str->charset(); | |
| 6207 | |||
| 6208 | size_t valid_length; | ||
| 6209 | bool length_error; | ||
| 6210 | |||
| 6211 |
3/4✓ Branch 0 taken 50134718 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4437 times.
✓ Branch 3 taken 50130281 times.
|
50134949 | if (validate_string(cs, str->ptr(), str->length(), &valid_length, |
| 6212 | &length_error)) { | ||
| 6213 | 4437 | const char *str_end = str->ptr() + str->length(); | |
| 6214 | 4437 | const char *print_byte = str->ptr() + valid_length; | |
| 6215 |
1/2✓ Branch 0 taken 4437 times.
✗ Branch 1 not taken.
|
4437 | THD *thd = current_thd; |
| 6216 | char hexbuf[7]; | ||
| 6217 | 4437 | size_t diff = min(size_t(str_end - print_byte), size_t(3)); | |
| 6218 |
1/2✓ Branch 0 taken 4437 times.
✗ Branch 1 not taken.
|
4437 | octet2hex(hexbuf, print_byte, diff); |
| 6219 |
4/4✓ Branch 0 taken 67 times.
✓ Branch 1 taken 4370 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 2 times.
|
4437 | if (send_error && length_error) { |
| 6220 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | my_error(ER_INVALID_CHARACTER_STRING, MYF(0), cs->csname, hexbuf); |
| 6221 | 65 | return nullptr; | |
| 6222 | } | ||
| 6223 |
4/4✓ Branch 0 taken 4166 times.
✓ Branch 1 taken 206 times.
✓ Branch 2 taken 4164 times.
✓ Branch 3 taken 2 times.
|
4372 | if (truncate && length_error) { |
| 6224 |
2/2✓ Branch 0 taken 68 times.
✓ Branch 1 taken 4096 times.
|
4164 | if (thd->is_strict_mode()) { |
| 6225 | 68 | null_value = true; | |
| 6226 | 68 | str = nullptr; | |
| 6227 | } else { | ||
| 6228 | 4096 | str->length(valid_length); | |
| 6229 | } | ||
| 6230 | } | ||
| 6231 |
1/2✓ Branch 0 taken 4372 times.
✗ Branch 1 not taken.
|
4372 | push_warning_printf( |
| 6232 | thd, Sql_condition::SL_WARNING, ER_INVALID_CHARACTER_STRING, | ||
| 6233 |
1/2✓ Branch 0 taken 4372 times.
✗ Branch 1 not taken.
|
4372 | ER_THD(thd, ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); |
| 6234 | } | ||
| 6235 | 50134653 | return str; | |
| 6236 | } | ||
| 6237 | |||
| 6238 | /* | ||
| 6239 | Compare two items using a given collation | ||
| 6240 | |||
| 6241 | SYNOPSIS | ||
| 6242 | eq_by_collation() | ||
| 6243 | item item to compare with | ||
| 6244 | binary_cmp true <-> compare as binaries | ||
| 6245 | cs collation to use when comparing strings | ||
| 6246 | |||
| 6247 | DESCRIPTION | ||
| 6248 | This method works exactly as Item::eq if the collation cs coincides with | ||
| 6249 | the collation of the compared objects. Otherwise, first the collations that | ||
| 6250 | differ from cs are replaced for cs and then the items are compared by | ||
| 6251 | Item::eq. After the comparison the original collations of items are | ||
| 6252 | restored. | ||
| 6253 | |||
| 6254 | RETURN | ||
| 6255 | 1 compared items has been detected as equal | ||
| 6256 | 0 otherwise | ||
| 6257 | */ | ||
| 6258 | |||
| 6259 | 2465 | bool Item::eq_by_collation(Item *item, bool binary_cmp, | |
| 6260 | const CHARSET_INFO *cs) { | ||
| 6261 | 2465 | const CHARSET_INFO *save_cs = nullptr; | |
| 6262 | 2465 | const CHARSET_INFO *save_item_cs = nullptr; | |
| 6263 |
2/2✓ Branch 0 taken 194 times.
✓ Branch 1 taken 2271 times.
|
2465 | if (collation.collation != cs) { |
| 6264 | 194 | save_cs = collation.collation; | |
| 6265 | 194 | collation.collation = cs; | |
| 6266 | } | ||
| 6267 |
2/2✓ Branch 0 taken 315 times.
✓ Branch 1 taken 2150 times.
|
2465 | if (item->collation.collation != cs) { |
| 6268 | 315 | save_item_cs = item->collation.collation; | |
| 6269 | 315 | item->collation.collation = cs; | |
| 6270 | } | ||
| 6271 | 2465 | bool res = eq(item, binary_cmp); | |
| 6272 |
2/2✓ Branch 0 taken 194 times.
✓ Branch 1 taken 2271 times.
|
2465 | if (save_cs) collation.collation = save_cs; |
| 6273 |
2/2✓ Branch 0 taken 315 times.
✓ Branch 1 taken 2150 times.
|
2465 | if (save_item_cs) item->collation.collation = save_item_cs; |
| 6274 | 2465 | return res; | |
| 6275 | } | ||
| 6276 | |||
| 6277 | /** | ||
| 6278 | Create a field to hold a string value from an item. | ||
| 6279 | |||
| 6280 | If max_length > CONVERT_IF_BIGGER_TO_BLOB create a blob @n | ||
| 6281 | If max_length > 0 create a varchar @n | ||
| 6282 | If max_length == 0 create a CHAR(0) | ||
| 6283 | |||
| 6284 | @param table Table for which the field is created | ||
| 6285 | */ | ||
| 6286 | |||
| 6287 | 1189963 | Field *Item::make_string_field(TABLE *table) const { | |
| 6288 | Field *field; | ||
| 6289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1189963 times.
|
1189963 | assert(collation.collation); |
| 6290 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1189954 times.
|
1189963 | if (data_type() == MYSQL_TYPE_JSON) |
| 6291 | 9 | field = | |
| 6292 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | new (*THR_MALLOC) Field_json(max_length, m_nullable, item_name.ptr()); |
| 6293 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1189948 times.
|
1189954 | else if (data_type() == MYSQL_TYPE_GEOMETRY) { |
| 6294 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
18 | field = new (*THR_MALLOC) |
| 6295 | 6 | Field_geom(max_length, m_nullable, item_name.ptr(), | |
| 6296 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
24 | Field::GEOM_GEOMETRY, std::optional<gis::srid_t>()); |
| 6297 |
2/2✓ Branch 0 taken 287583 times.
✓ Branch 1 taken 902365 times.
|
1189948 | } else if (max_length / collation.collation->mbmaxlen > |
| 6298 | CONVERT_IF_BIGGER_TO_BLOB) | ||
| 6299 |
1/2✓ Branch 0 taken 287583 times.
✗ Branch 1 not taken.
|
862749 | field = new (*THR_MALLOC) Field_blob( |
| 6300 |
1/2✓ Branch 0 taken 287583 times.
✗ Branch 1 not taken.
|
862749 | max_length, m_nullable, item_name.ptr(), collation.collation, true); |
| 6301 | /* Item_type_holder holds the exact type, do not change it */ | ||
| 6302 |
4/4✓ Branch 0 taken 884085 times.
✓ Branch 1 taken 18280 times.
✓ Branch 2 taken 883818 times.
✓ Branch 3 taken 18547 times.
|
1786450 | else if (max_length > 0 && |
| 6303 |
4/4✓ Branch 0 taken 111261 times.
✓ Branch 1 taken 772824 times.
✓ Branch 2 taken 110994 times.
✓ Branch 3 taken 267 times.
|
884085 | (type() != Item::TYPE_HOLDER || data_type() != MYSQL_TYPE_STRING)) |
| 6304 |
1/2✓ Branch 0 taken 883818 times.
✗ Branch 1 not taken.
|
2651454 | field = new (*THR_MALLOC) Field_varstring( |
| 6305 |
1/2✓ Branch 0 taken 883818 times.
✗ Branch 1 not taken.
|
2651454 | max_length, m_nullable, item_name.ptr(), table->s, collation.collation); |
| 6306 | else | ||
| 6307 |
1/2✓ Branch 0 taken 18547 times.
✗ Branch 1 not taken.
|
55641 | field = new (*THR_MALLOC) Field_string( |
| 6308 |
1/2✓ Branch 0 taken 18547 times.
✗ Branch 1 not taken.
|
55641 | max_length, m_nullable, item_name.ptr(), collation.collation); |
| 6309 |
1/2✓ Branch 0 taken 1189963 times.
✗ Branch 1 not taken.
|
1189963 | if (field) field->init(table); |
| 6310 | 1189963 | return field; | |
| 6311 | } | ||
| 6312 | |||
| 6313 | /** | ||
| 6314 | Create a field based on field_type of argument. | ||
| 6315 | |||
| 6316 | For now, this is only used to create a field for | ||
| 6317 | IFNULL(x,something) and time functions | ||
| 6318 | |||
| 6319 | @return Created field | ||
| 6320 | @retval NULL error | ||
| 6321 | */ | ||
| 6322 | |||
| 6323 | 2336312 | Field *Item::tmp_table_field_from_field_type(TABLE *table, | |
| 6324 | bool fixed_length) const { | ||
| 6325 | /* | ||
| 6326 | The field functions defines a field to be not null if null_ptr is not 0 | ||
| 6327 | */ | ||
| 6328 | Field *field; | ||
| 6329 | |||
| 6330 |
19/20✓ Branch 0 taken 11402 times.
✓ Branch 1 taken 1132 times.
✓ Branch 2 taken 2268 times.
✓ Branch 3 taken 277172 times.
✓ Branch 4 taken 1322994 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 67832 times.
✓ Branch 7 taken 13 times.
✓ Branch 8 taken 239 times.
✓ Branch 9 taken 34409 times.
✓ Branch 10 taken 53 times.
✓ Branch 11 taken 164083 times.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 302 times.
✓ Branch 16 taken 442397 times.
✓ Branch 17 taken 11546 times.
✓ Branch 18 taken 194 times.
✓ Branch 19 taken 263 times.
|
2336312 | switch (data_type()) { |
| 6331 | 11402 | case MYSQL_TYPE_DECIMAL: | |
| 6332 | case MYSQL_TYPE_NEWDECIMAL: | ||
| 6333 | 11402 | field = Field_new_decimal::create_from_item(this); | |
| 6334 | 11402 | break; | |
| 6335 | 1132 | case MYSQL_TYPE_TINY: | |
| 6336 |
1/2✓ Branch 0 taken 1132 times.
✗ Branch 1 not taken.
|
3396 | field = new (*THR_MALLOC) |
| 6337 |
1/2✓ Branch 0 taken 1132 times.
✗ Branch 1 not taken.
|
3396 | Field_tiny(max_length, m_nullable, item_name.ptr(), unsigned_flag); |
| 6338 | 1132 | break; | |
| 6339 | 2268 | case MYSQL_TYPE_SHORT: | |
| 6340 |
1/2✓ Branch 0 taken 2268 times.
✗ Branch 1 not taken.
|
6804 | field = new (*THR_MALLOC) |
| 6341 |
1/2✓ Branch 0 taken 2268 times.
✗ Branch 1 not taken.
|
6804 | Field_short(max_length, m_nullable, item_name.ptr(), unsigned_flag); |
| 6342 | 2268 | break; | |
| 6343 | 277172 | case MYSQL_TYPE_LONG: | |
| 6344 |
1/2✓ Branch 0 taken 277172 times.
✗ Branch 1 not taken.
|
831516 | field = new (*THR_MALLOC) |
| 6345 |
1/2✓ Branch 0 taken 277172 times.
✗ Branch 1 not taken.
|
831516 | Field_long(max_length, m_nullable, item_name.ptr(), unsigned_flag); |
| 6346 | 277172 | break; | |
| 6347 | 1322994 | case MYSQL_TYPE_LONGLONG: | |
| 6348 |
1/2✓ Branch 0 taken 1322994 times.
✗ Branch 1 not taken.
|
3968982 | field = new (*THR_MALLOC) Field_longlong(max_length, m_nullable, |
| 6349 |
1/2✓ Branch 0 taken 1322994 times.
✗ Branch 1 not taken.
|
3968982 | item_name.ptr(), unsigned_flag); |
| 6350 | 1322994 | break; | |
| 6351 | 5 | case MYSQL_TYPE_FLOAT: | |
| 6352 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
15 | field = new (*THR_MALLOC) Field_float( |
| 6353 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
15 | max_length, m_nullable, item_name.ptr(), decimals, unsigned_flag); |
| 6354 | 5 | break; | |
| 6355 | 67832 | case MYSQL_TYPE_DOUBLE: | |
| 6356 |
1/2✓ Branch 0 taken 67832 times.
✗ Branch 1 not taken.
|
203496 | field = new (*THR_MALLOC) Field_double( |
| 6357 |
1/2✓ Branch 0 taken 67832 times.
✗ Branch 1 not taken.
|
203496 | max_length, m_nullable, item_name.ptr(), decimals, unsigned_flag); |
| 6358 | 67832 | break; | |
| 6359 | 13 | case MYSQL_TYPE_INT24: | |
| 6360 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
39 | field = new (*THR_MALLOC) |
| 6361 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
39 | Field_medium(max_length, m_nullable, item_name.ptr(), unsigned_flag); |
| 6362 | 13 | break; | |
| 6363 | 239 | case MYSQL_TYPE_DATE: | |
| 6364 | case MYSQL_TYPE_NEWDATE: | ||
| 6365 |
2/4✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
|
239 | field = new (*THR_MALLOC) Field_newdate(m_nullable, item_name.ptr()); |
| 6366 | 239 | break; | |
| 6367 | 34409 | case MYSQL_TYPE_TIME: | |
| 6368 | 34409 | field = | |
| 6369 |
2/4✓ Branch 0 taken 34409 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34409 times.
✗ Branch 3 not taken.
|
34409 | new (*THR_MALLOC) Field_timef(m_nullable, item_name.ptr(), decimals); |
| 6370 | 34409 | break; | |
| 6371 | 53 | case MYSQL_TYPE_TIMESTAMP: | |
| 6372 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
159 | field = new (*THR_MALLOC) |
| 6373 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
159 | Field_timestampf(m_nullable, item_name.ptr(), decimals); |
| 6374 | 53 | break; | |
| 6375 | 164083 | case MYSQL_TYPE_DATETIME: | |
| 6376 |
1/2✓ Branch 0 taken 164083 times.
✗ Branch 1 not taken.
|
492249 | field = new (*THR_MALLOC) |
| 6377 |
1/2✓ Branch 0 taken 164083 times.
✗ Branch 1 not taken.
|
492249 | Field_datetimef(m_nullable, item_name.ptr(), decimals); |
| 6378 | 164083 | break; | |
| 6379 | 4 | case MYSQL_TYPE_YEAR: | |
| 6380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(max_length == 4); // Field_year is only for length 4. |
| 6381 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | field = new (*THR_MALLOC) Field_year(m_nullable, item_name.ptr()); |
| 6382 | 4 | break; | |
| 6383 | 4 | case MYSQL_TYPE_BIT: | |
| 6384 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
12 | field = new (*THR_MALLOC) |
| 6385 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
12 | Field_bit_as_char(max_length, m_nullable, item_name.ptr()); |
| 6386 | 4 | break; | |
| 6387 | ✗ | case MYSQL_TYPE_INVALID: | |
| 6388 | case MYSQL_TYPE_BOOL: | ||
| 6389 | default: | ||
| 6390 | /* This case should never be chosen */ | ||
| 6391 | ✗ | assert(0); | |
| 6392 | /* If something goes awfully wrong, it's better to get a string than die | ||
| 6393 | */ | ||
| 6394 | 302 | case MYSQL_TYPE_STRING: | |
| 6395 | case MYSQL_TYPE_NULL: | ||
| 6396 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 302 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
302 | if (fixed_length && max_length <= CONVERT_IF_BIGGER_TO_BLOB) { |
| 6397 | ✗ | field = new (*THR_MALLOC) Field_string( | |
| 6398 | ✗ | max_length, m_nullable, item_name.ptr(), collation.collation); | |
| 6399 | ✗ | break; | |
| 6400 | } | ||
| 6401 | /* Fall through to make_string_field() */ | ||
| 6402 | [[fallthrough]]; | ||
| 6403 | case MYSQL_TYPE_ENUM: | ||
| 6404 | case MYSQL_TYPE_SET: | ||
| 6405 | case MYSQL_TYPE_VAR_STRING: | ||
| 6406 | case MYSQL_TYPE_VARCHAR: | ||
| 6407 | 442699 | return make_string_field(table); | |
| 6408 | 11546 | case MYSQL_TYPE_TINY_BLOB: | |
| 6409 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 6410 | case MYSQL_TYPE_LONG_BLOB: | ||
| 6411 | case MYSQL_TYPE_BLOB: | ||
| 6412 |
2/2✓ Branch 0 taken 11365 times.
✓ Branch 1 taken 181 times.
|
11546 | if (this->type() == Item::TYPE_HOLDER) |
| 6413 |
1/2✓ Branch 0 taken 11365 times.
✗ Branch 1 not taken.
|
34095 | field = new (*THR_MALLOC) Field_blob( |
| 6414 |
1/2✓ Branch 0 taken 11365 times.
✗ Branch 1 not taken.
|
34095 | max_length, m_nullable, item_name.ptr(), collation.collation, true); |
| 6415 | else | ||
| 6416 |
1/2✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
|
543 | field = new (*THR_MALLOC) |
| 6417 | 181 | Field_blob(max_length, m_nullable, item_name.ptr(), | |
| 6418 |
1/2✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
|
362 | collation.collation, false); |
| 6419 | 11546 | break; // Blob handled outside of case | |
| 6420 | 194 | case MYSQL_TYPE_GEOMETRY: | |
| 6421 |
2/4✓ Branch 0 taken 194 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 194 times.
✗ Branch 3 not taken.
|
582 | field = new (*THR_MALLOC) Field_geom( |
| 6422 |
1/2✓ Branch 0 taken 194 times.
✗ Branch 1 not taken.
|
582 | max_length, m_nullable, item_name.ptr(), get_geometry_type(), {}); |
| 6423 | 194 | break; | |
| 6424 | 263 | case MYSQL_TYPE_JSON: | |
| 6425 | 263 | field = | |
| 6426 |
2/4✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 263 times.
✗ Branch 3 not taken.
|
263 | new (*THR_MALLOC) Field_json(max_length, m_nullable, item_name.ptr()); |
| 6427 | } | ||
| 6428 |
1/2✓ Branch 0 taken 1893613 times.
✗ Branch 1 not taken.
|
1893613 | if (field) field->init(table); |
| 6429 | 1893613 | return field; | |
| 6430 | } | ||
| 6431 | |||
| 6432 | /* ARGSUSED */ | ||
| 6433 | 6737727 | void Item_field::make_field(Send_field *tmp_field) { | |
| 6434 | 6737727 | field->make_send_field(tmp_field); | |
| 6435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6737724 times.
|
6737724 | assert(tmp_field->table_name != nullptr); |
| 6436 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6737727 times.
|
6737724 | assert(item_name.is_set()); |
| 6437 | 6737727 | tmp_field->col_name = item_name.ptr(); // Use user supplied name | |
| 6438 |
2/2✓ Branch 0 taken 6649445 times.
✓ Branch 1 taken 88280 times.
|
6737725 | tmp_field->table_name = table_name != nullptr ? table_name : ""; |
| 6439 |
2/2✓ Branch 0 taken 6459877 times.
✓ Branch 1 taken 277848 times.
|
6737725 | tmp_field->db_name = m_orig_db_name != nullptr ? m_orig_db_name : ""; |
| 6440 | 6737725 | tmp_field->org_table_name = | |
| 6441 |
2/2✓ Branch 0 taken 5923668 times.
✓ Branch 1 taken 814057 times.
|
6737725 | m_orig_table_name != nullptr ? m_orig_table_name : ""; |
| 6442 | 6737725 | tmp_field->org_col_name = | |
| 6443 |
2/2✓ Branch 0 taken 6731786 times.
✓ Branch 1 taken 5939 times.
|
6737725 | m_orig_field_name != nullptr ? m_orig_field_name : ""; |
| 6444 | 6737725 | tmp_field->field = true; | |
| 6445 | 6737725 | } | |
| 6446 | |||
| 6447 | /** | ||
| 6448 | Copies/converts data from “from” to “to”, but is faster on repeated execution | ||
| 6449 | with the same “to” field, as it caches the fields_are_memcpyable() and | ||
| 6450 | pack_length() calls. These are not terribly expensive in themselves, but it | ||
| 6451 | adds up to 5–10% in DBT-3 Q1 due to the repeated calls. | ||
| 6452 | |||
| 6453 | The “from” field _must_ correspond to the same last_to / to_is_memcpyable pair | ||
| 6454 | as earlier calls, unless last_to is cleared to nullptr. | ||
| 6455 | */ | ||
| 6456 | 243572241 | static inline type_conversion_status field_conv_with_cache( | |
| 6457 | Field *to, Field *from, Field **last_to, uint32_t *to_is_memcpyable) { | ||
| 6458 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 243572536 times.
|
243572241 | assert(to->field_ptr() != from->field_ptr()); |
| 6459 |
2/2✓ Branch 0 taken 8539166 times.
✓ Branch 1 taken 235033370 times.
|
243572536 | if (to != *last_to) { |
| 6460 | 8539166 | *last_to = to; | |
| 6461 |
2/2✓ Branch 0 taken 6524646 times.
✓ Branch 1 taken 2014522 times.
|
8539166 | if (fields_are_memcpyable(to, from)) { |
| 6462 | 6524646 | *to_is_memcpyable = to->pack_length(); | |
| 6463 | } else { | ||
| 6464 | 2014522 | *to_is_memcpyable = -1; | |
| 6465 | } | ||
| 6466 | } | ||
| 6467 |
2/2✓ Branch 0 taken 119777667 times.
✓ Branch 1 taken 123794872 times.
|
243572539 | if (*to_is_memcpyable != static_cast<uint32_t>(-1)) { |
| 6468 | 119777667 | memcpy(to->field_ptr(), from->field_ptr(), *to_is_memcpyable); | |
| 6469 | 119777667 | return TYPE_OK; | |
| 6470 | } else { | ||
| 6471 | 123794872 | return field_conv_slow(to, from); | |
| 6472 | } | ||
| 6473 | } | ||
| 6474 | |||
| 6475 | /** | ||
| 6476 | Set a field's value from a item. | ||
| 6477 | */ | ||
| 6478 | |||
| 6479 | 5820869 | void Item_field::save_org_in_field(Field *to) { | |
| 6480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5820869 times.
|
5820869 | if (field == to) { |
| 6481 | ✗ | assert(null_value == field->is_null()); | |
| 6482 | ✗ | return; | |
| 6483 |
2/2✓ Branch 0 taken 2538 times.
✓ Branch 1 taken 5818331 times.
|
5820869 | } else if (field->is_null()) { |
| 6484 | 2538 | null_value = true; | |
| 6485 | 2538 | set_field_to_null_with_conversions(to, true); | |
| 6486 | } else { | ||
| 6487 | 5818331 | to->set_notnull(); | |
| 6488 | 5818331 | field_conv_with_cache(to, field, &last_org_destination_field, | |
| 6489 | &last_org_destination_field_memcpyable); | ||
| 6490 | 5818331 | null_value = false; | |
| 6491 | } | ||
| 6492 | } | ||
| 6493 | |||
| 6494 | 252168792 | type_conversion_status Item_field::save_in_field_inner(Field *to, | |
| 6495 | bool no_conversions) { | ||
| 6496 |
1/2✓ Branch 0 taken 252169208 times.
✗ Branch 1 not taken.
|
252168792 | DBUG_TRACE; |
| 6497 |
3/4✓ Branch 0 taken 252169046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14414085 times.
✓ Branch 3 taken 237754961 times.
|
252169208 | if (field->is_null()) { |
| 6498 | 14414085 | null_value = true; | |
| 6499 | const type_conversion_status status = | ||
| 6500 |
1/2✓ Branch 0 taken 14414085 times.
✗ Branch 1 not taken.
|
14414085 | set_field_to_null_with_conversions(to, no_conversions); |
| 6501 | 14414085 | return status; | |
| 6502 | } | ||
| 6503 |
1/2✓ Branch 0 taken 237755044 times.
✗ Branch 1 not taken.
|
237754961 | to->set_notnull(); |
| 6504 | 237755044 | null_value = false; | |
| 6505 | |||
| 6506 | /* | ||
| 6507 | If we're setting the same field as the one we're reading from there's | ||
| 6508 | nothing to do. This can happen in 'SET x = x' type of scenarios. | ||
| 6509 | */ | ||
| 6510 |
2/2✓ Branch 0 taken 855 times.
✓ Branch 1 taken 237754189 times.
|
237755044 | if (to == field) { |
| 6511 | 855 | return TYPE_OK; | |
| 6512 | } | ||
| 6513 |
1/2✓ Branch 0 taken 237754150 times.
✗ Branch 1 not taken.
|
237754189 | return field_conv_with_cache(to, field, &last_destination_field, |
| 6514 | 237754150 | &last_destination_field_memcpyable); | |
| 6515 | 252169090 | } | |
| 6516 | |||
| 6517 | /** | ||
| 6518 | Store null in field. | ||
| 6519 | |||
| 6520 | This is used on INSERT. | ||
| 6521 | Allow NULL to be inserted in timestamp and auto_increment values. | ||
| 6522 | |||
| 6523 | @param field Field where we want to store NULL | ||
| 6524 | @param no_conversions Set to 1 if we should return 1 if field can't | ||
| 6525 | take null values. | ||
| 6526 | If set to 0 we will do store the 'default value' | ||
| 6527 | if the field is a special field. If not we will | ||
| 6528 | give an error. | ||
| 6529 | |||
| 6530 | @retval | ||
| 6531 | 0 ok | ||
| 6532 | @retval | ||
| 6533 | 1 Field doesn't support NULL values and can't handle 'field = NULL' | ||
| 6534 | */ | ||
| 6535 | |||
| 6536 | 4571015 | type_conversion_status Item_null::save_in_field_inner(Field *field, | |
| 6537 | bool no_conversions) { | ||
| 6538 | 4571015 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 6539 | } | ||
| 6540 | |||
| 6541 | 391608771 | type_conversion_status Item::save_in_field(Field *field, bool no_conversions) { | |
| 6542 |
1/2✓ Branch 0 taken 391611456 times.
✗ Branch 1 not taken.
|
391608771 | DBUG_TRACE; |
| 6543 | // In case this is a hidden column used for a functional index, insert | ||
| 6544 | // an error handler that catches any errors that tries to print out the | ||
| 6545 | // name of the hidden column. It will instead print out the functional | ||
| 6546 | // index name. | ||
| 6547 | |||
| 6548 | Functional_index_error_handler functional_index_error_handler(field, | ||
| 6549 |
2/4✓ Branch 0 taken 391610734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 391611211 times.
✗ Branch 3 not taken.
|
391611456 | current_thd); |
| 6550 | |||
| 6551 |
1/2✓ Branch 0 taken 391609711 times.
✗ Branch 1 not taken.
|
391611211 | const type_conversion_status ret = save_in_field_inner(field, no_conversions); |
| 6552 | |||
| 6553 | /* | ||
| 6554 | If an error was raised during evaluation of the item, | ||
| 6555 | save_in_field_inner() might not notice and return TYPE_OK. Make | ||
| 6556 | sure that we return not OK if there was an error. | ||
| 6557 | */ | ||
| 6558 |
8/10✓ Branch 0 taken 389039033 times.
✓ Branch 1 taken 2570678 times.
✓ Branch 2 taken 389039437 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 389039354 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1484 times.
✓ Branch 7 taken 389037870 times.
✓ Branch 8 taken 1484 times.
✓ Branch 9 taken 391608548 times.
|
391609711 | if (ret == TYPE_OK && current_thd->is_error()) { |
| 6559 | 1484 | return TYPE_ERR_BAD_VALUE; | |
| 6560 | } | ||
| 6561 | 391608548 | return ret; | |
| 6562 | 391610032 | } | |
| 6563 | |||
| 6564 | /* | ||
| 6565 | This implementation can lose str_value content, so if the | ||
| 6566 | Item uses str_value to store something, it should | ||
| 6567 | reimplement its ::save_in_field_inner() as Item_string, for example, does. | ||
| 6568 | |||
| 6569 | Note: all Item_XXX::val_str(str) methods must NOT rely on the fact that | ||
| 6570 | str != str_value. For example, see fix for bug #44743. | ||
| 6571 | */ | ||
| 6572 | |||
| 6573 | 144967712 | type_conversion_status Item::save_in_field_inner(Field *field, | |
| 6574 | bool no_conversions) { | ||
| 6575 | // Storing of arrays should be handled by specialized subclasses. | ||
| 6576 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144967956 times.
|
144967712 | assert(!returns_array()); |
| 6577 | |||
| 6578 |
2/2✓ Branch 0 taken 96566846 times.
✓ Branch 1 taken 48400792 times.
|
144967956 | if (result_type() == STRING_RESULT) { |
| 6579 |
1/2✓ Branch 0 taken 96566907 times.
✗ Branch 1 not taken.
|
96566846 | const enum Type typ = type(); |
| 6580 | |||
| 6581 |
4/4✓ Branch 0 taken 22887 times.
✓ Branch 1 taken 96544020 times.
✓ Branch 2 taken 2013 times.
✓ Branch 3 taken 20874 times.
|
96566907 | if (typ == FUNC_ITEM || typ == SUBSELECT_ITEM) { |
| 6582 | 96546033 | enum_field_types ft = data_type(); | |
| 6583 | // Avoid JSON dom/binary serialization to/from string | ||
| 6584 |
2/2✓ Branch 0 taken 442655 times.
✓ Branch 1 taken 96103482 times.
|
96546137 | if (ft == MYSQL_TYPE_JSON) { |
| 6585 |
3/4✓ Branch 0 taken 442478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22214 times.
✓ Branch 3 taken 420264 times.
|
442655 | if (field->type() == MYSQL_TYPE_JSON) { |
| 6586 | // Store the value in the JSON binary format. | ||
| 6587 | 22214 | Field_json *f = down_cast<Field_json *>(field); | |
| 6588 | 22214 | Json_wrapper wr; | |
| 6589 |
3/4✓ Branch 0 taken 22214 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 22204 times.
|
22214 | if (val_json(&wr)) return TYPE_ERR_BAD_VALUE; |
| 6590 | |||
| 6591 |
3/4✓ Branch 0 taken 1058 times.
✓ Branch 1 taken 21146 times.
✓ Branch 2 taken 1058 times.
✗ Branch 3 not taken.
|
22204 | if (null_value) return set_field_to_null(field); |
| 6592 | |||
| 6593 |
1/2✓ Branch 0 taken 21146 times.
✗ Branch 1 not taken.
|
21146 | field->set_notnull(); |
| 6594 |
1/2✓ Branch 0 taken 21146 times.
✗ Branch 1 not taken.
|
21146 | return f->store_json(&wr); |
| 6595 | 22214 | } | |
| 6596 | |||
| 6597 |
1/2✓ Branch 0 taken 420204 times.
✗ Branch 1 not taken.
|
420264 | const enum_field_types field_type = field->type(); |
| 6598 |
6/6✓ Branch 0 taken 283 times.
✓ Branch 1 taken 419999 times.
✓ Branch 2 taken 227 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 227 times.
✓ Branch 5 taken 420055 times.
|
420204 | if (is_temporal_type(field_type) && field_type != MYSQL_TYPE_YEAR) { |
| 6599 | MYSQL_TIME t; | ||
| 6600 | 227 | bool res = true; | |
| 6601 |
2/4✓ Branch 0 taken 56 times.
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
227 | switch (field_type) { |
| 6602 | 56 | case MYSQL_TYPE_TIME: | |
| 6603 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | res = get_time(&t); |
| 6604 | 56 | break; | |
| 6605 | 171 | case MYSQL_TYPE_DATETIME: | |
| 6606 | case MYSQL_TYPE_TIMESTAMP: | ||
| 6607 | case MYSQL_TYPE_DATE: | ||
| 6608 | case MYSQL_TYPE_NEWDATE: | ||
| 6609 |
1/2✓ Branch 0 taken 171 times.
✗ Branch 1 not taken.
|
171 | res = get_date(&t, 0); |
| 6610 | 171 | break; | |
| 6611 | ✗ | case MYSQL_TYPE_YEAR: | |
| 6612 | ✗ | assert(false); | |
| 6613 | ✗ | default: | |
| 6614 | ✗ | assert(false); | |
| 6615 | } | ||
| 6616 |
2/2✓ Branch 0 taken 210 times.
✓ Branch 1 taken 17 times.
|
227 | if (res) { |
| 6617 | 210 | null_value = true; | |
| 6618 |
1/2✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
|
210 | return set_field_to_null_with_conversions(field, no_conversions); |
| 6619 | } | ||
| 6620 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | field->set_notnull(); |
| 6621 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | return field->store_time(&t); |
| 6622 | } | ||
| 6623 |
3/4✓ Branch 0 taken 419980 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 419908 times.
|
420055 | if (field->type() == MYSQL_TYPE_NEWDECIMAL) { |
| 6624 | 72 | my_decimal decimal_value; | |
| 6625 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | my_decimal *value = val_decimal(&decimal_value); |
| 6626 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 64 times.
|
72 | if (null_value) |
| 6627 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | return set_field_to_null_with_conversions(field, no_conversions); |
| 6628 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | field->set_notnull(); |
| 6629 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | return field->store_decimal(value); |
| 6630 | 72 | } | |
| 6631 |
1/2✓ Branch 0 taken 419880 times.
✗ Branch 1 not taken.
|
419908 | if (field->type() == MYSQL_TYPE_INT24 || |
| 6632 |
3/4✓ Branch 0 taken 419824 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 419730 times.
✓ Branch 3 taken 94 times.
|
419795 | field->type() == MYSQL_TYPE_TINY || |
| 6633 |
3/4✓ Branch 0 taken 419804 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 419694 times.
✓ Branch 3 taken 110 times.
|
419730 | field->type() == MYSQL_TYPE_SHORT || |
| 6634 |
7/8✓ Branch 0 taken 419795 times.
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 419706 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1925 times.
✓ Branch 5 taken 417781 times.
✓ Branch 6 taken 418179 times.
✓ Branch 7 taken 1816 times.
|
841703 | field->type() == MYSQL_TYPE_LONG || |
| 6635 |
3/4✓ Branch 0 taken 1925 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 122 times.
✓ Branch 3 taken 1803 times.
|
1925 | field->type() == MYSQL_TYPE_LONGLONG) { |
| 6636 |
1/2✓ Branch 0 taken 418094 times.
✗ Branch 1 not taken.
|
418179 | longlong nr = val_int(); |
| 6637 |
2/2✓ Branch 0 taken 125 times.
✓ Branch 1 taken 417969 times.
|
418094 | if (null_value) |
| 6638 |
1/2✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
|
125 | return set_field_to_null_with_conversions(field, no_conversions); |
| 6639 |
1/2✓ Branch 0 taken 418120 times.
✗ Branch 1 not taken.
|
417969 | field->set_notnull(); |
| 6640 |
1/2✓ Branch 0 taken 418203 times.
✗ Branch 1 not taken.
|
418120 | return field->store(nr, unsigned_flag); |
| 6641 | } | ||
| 6642 |
5/6✓ Branch 0 taken 1803 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1747 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 116 times.
✓ Branch 5 taken 1687 times.
|
3563 | if (field->type() == MYSQL_TYPE_FLOAT || |
| 6643 |
3/4✓ Branch 0 taken 1747 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 1687 times.
|
1747 | field->type() == MYSQL_TYPE_DOUBLE) { |
| 6644 |
1/2✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
|
116 | double nr = val_real(); |
| 6645 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 100 times.
|
116 | if (null_value) |
| 6646 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | return set_field_to_null_with_conversions(field, no_conversions); |
| 6647 |
1/2✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
|
100 | field->set_notnull(); |
| 6648 |
1/2✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
|
100 | return field->store(nr); |
| 6649 | } | ||
| 6650 | } | ||
| 6651 | } | ||
| 6652 | |||
| 6653 | String *result; | ||
| 6654 | 96126043 | const CHARSET_INFO *cs = collation.collation; | |
| 6655 | char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns | ||
| 6656 | 96126043 | str_value.set_quick(buff, sizeof(buff), cs); | |
| 6657 |
1/2✓ Branch 0 taken 96126677 times.
✗ Branch 1 not taken.
|
96125955 | result = val_str(&str_value); |
| 6658 |
4/6✓ Branch 0 taken 96126553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96126759 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 169 times.
✓ Branch 5 taken 96126590 times.
|
96126677 | if (current_thd->is_error()) return TYPE_ERR_BAD_VALUE; |
| 6659 |
2/2✓ Branch 0 taken 9312821 times.
✓ Branch 1 taken 86813769 times.
|
96126590 | if (null_value) { |
| 6660 | 9312821 | str_value.set_quick(nullptr, 0, cs); | |
| 6661 |
1/2✓ Branch 0 taken 9312821 times.
✗ Branch 1 not taken.
|
9312821 | return set_field_to_null_with_conversions(field, no_conversions); |
| 6662 | } | ||
| 6663 | |||
| 6664 | /* NOTE: If null_value == false, "result" must be not NULL. */ | ||
| 6665 | |||
| 6666 |
1/2✓ Branch 0 taken 86813641 times.
✗ Branch 1 not taken.
|
86813769 | field->set_notnull(); |
| 6667 | type_conversion_status error = | ||
| 6668 |
1/2✓ Branch 0 taken 86813250 times.
✗ Branch 1 not taken.
|
86813202 | field->store(result->ptr(), result->length(), |
| 6669 |
3/4✓ Branch 0 taken 86813202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2259 times.
✓ Branch 3 taken 86810943 times.
|
86813641 | field->type() == MYSQL_TYPE_JSON ? result->charset() : cs); |
| 6670 | 86813250 | str_value.set_quick(nullptr, 0, cs); | |
| 6671 | 86813379 | return error; | |
| 6672 | } | ||
| 6673 | |||
| 6674 |
6/6✓ Branch 0 taken 951534 times.
✓ Branch 1 taken 47449309 times.
✓ Branch 2 taken 4578 times.
✓ Branch 3 taken 946962 times.
✓ Branch 4 taken 4578 times.
✓ Branch 5 taken 48396271 times.
|
48400792 | if (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT) { |
| 6675 | 4578 | double nr = val_real(); | |
| 6676 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4566 times.
|
4578 | if (null_value) |
| 6677 | 12 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 6678 | 4566 | field->set_notnull(); | |
| 6679 | 4566 | return field->store(nr); | |
| 6680 | } | ||
| 6681 | |||
| 6682 |
2/2✓ Branch 0 taken 946964 times.
✓ Branch 1 taken 47449357 times.
|
48396271 | if (result_type() == REAL_RESULT) { |
| 6683 | 946964 | double nr = val_real(); | |
| 6684 |
2/2✓ Branch 0 taken 5444 times.
✓ Branch 1 taken 941522 times.
|
946966 | if (null_value) |
| 6685 | 5444 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 6686 | 941522 | field->set_notnull(); | |
| 6687 | 941523 | return field->store(nr); | |
| 6688 | } | ||
| 6689 | |||
| 6690 |
2/2✓ Branch 0 taken 1621113 times.
✓ Branch 1 taken 45828274 times.
|
47449357 | if (result_type() == DECIMAL_RESULT) { |
| 6691 | 1621113 | my_decimal decimal_value; | |
| 6692 |
1/2✓ Branch 0 taken 1621113 times.
✗ Branch 1 not taken.
|
1621113 | my_decimal *value = val_decimal(&decimal_value); |
| 6693 |
2/2✓ Branch 0 taken 4532 times.
✓ Branch 1 taken 1616581 times.
|
1621113 | if (null_value) |
| 6694 |
1/2✓ Branch 0 taken 4532 times.
✗ Branch 1 not taken.
|
4532 | return set_field_to_null_with_conversions(field, no_conversions); |
| 6695 |
1/2✓ Branch 0 taken 1616581 times.
✗ Branch 1 not taken.
|
1616581 | field->set_notnull(); |
| 6696 |
1/2✓ Branch 0 taken 1616581 times.
✗ Branch 1 not taken.
|
1616581 | return field->store_decimal(value); |
| 6697 | 1621113 | } | |
| 6698 | |||
| 6699 | 45828274 | longlong nr = val_int(); | |
| 6700 |
2/2✓ Branch 0 taken 19937607 times.
✓ Branch 1 taken 25890632 times.
|
45828239 | if (null_value) |
| 6701 | 19937607 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 6702 | 25890632 | field->set_notnull(); | |
| 6703 | 25890909 | return field->store(nr, unsigned_flag); | |
| 6704 | } | ||
| 6705 | |||
| 6706 | 20644308 | type_conversion_status Item_string::save_in_field_inner(Field *field, bool) { | |
| 6707 | String *result; | ||
| 6708 | 20644308 | result = val_str(&str_value); | |
| 6709 | 20644431 | return save_str_value_in_field(field, result); | |
| 6710 | } | ||
| 6711 | |||
| 6712 | 440 | type_conversion_status Item_uint::save_in_field_inner(Field *field, | |
| 6713 | bool no_conversions) { | ||
| 6714 | /* Item_int::save_in_field_inner handles both signed and unsigned. */ | ||
| 6715 | 440 | return Item_int::save_in_field_inner(field, no_conversions); | |
| 6716 | } | ||
| 6717 | |||
| 6718 | /** | ||
| 6719 | Store an int in a field | ||
| 6720 | |||
| 6721 | @param field The field where the int value is to be stored | ||
| 6722 | @param nr The value to store in field | ||
| 6723 | @param null_value True if the value to store is NULL, false otherwise | ||
| 6724 | @param unsigned_flag Whether or not the int value is signed or unsigned | ||
| 6725 | |||
| 6726 | @retval TYPE_OK Storing of value went fine without warnings or errors | ||
| 6727 | @retval !TYPE_OK Warning/error as indicated by type_conversion_status enum | ||
| 6728 | value | ||
| 6729 | */ | ||
| 6730 | 32430411 | static type_conversion_status save_int_value_in_field(Field *field, longlong nr, | |
| 6731 | bool null_value, | ||
| 6732 | bool unsigned_flag) { | ||
| 6733 | // TODO: call set_field_to_null_with_conversions below | ||
| 6734 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32430411 times.
|
32430411 | if (null_value) return set_field_to_null(field); |
| 6735 | 32430411 | field->set_notnull(); | |
| 6736 | 32431440 | return field->store(nr, unsigned_flag); | |
| 6737 | } | ||
| 6738 | |||
| 6739 | /** | ||
| 6740 | Store this item's int-value in a field | ||
| 6741 | |||
| 6742 | @param field The field where the int value is to be stored | ||
| 6743 | @param no_conversions Only applies if the value to store is NULL | ||
| 6744 | (null_value is true) and NULL is not allowed | ||
| 6745 | in field. In that case: if no_coversion is | ||
| 6746 | true, do nothing and return with error | ||
| 6747 | TYPE_ERR_NULL_CONSTRAINT_VIOLATION. If | ||
| 6748 | no_coversion is false, the field's default | ||
| 6749 | value is stored if one exists. Otherwise an | ||
| 6750 | error is returned. | ||
| 6751 | |||
| 6752 | @retval TYPE_OK Storing of value went fine without warnings or errors | ||
| 6753 | @retval !TYPE_OK Warning/error as indicated by type_conversion_status enum | ||
| 6754 | value | ||
| 6755 | */ | ||
| 6756 | 32430333 | type_conversion_status Item_int::save_in_field_inner(Field *field, | |
| 6757 | bool no_conversions | ||
| 6758 | [[maybe_unused]]) { | ||
| 6759 | 32430333 | return save_int_value_in_field(field, val_int(), null_value, unsigned_flag); | |
| 6760 | } | ||
| 6761 | |||
| 6762 | 43 | type_conversion_status Item_temporal::save_in_field_inner(Field *field, bool) { | |
| 6763 | 43 | const enum_field_types field_type = field->type(); | |
| 6764 | 43 | longlong nr = is_temporal_type_with_time(field_type) | |
| 6765 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | ? val_temporal_with_round(field_type, field->decimals()) |
| 6766 | ✗ | : val_date_temporal(); | |
| 6767 | // TODO: call set_field_to_null_with_conversions below | ||
| 6768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if (null_value) return set_field_to_null(field); |
| 6769 | 43 | field->set_notnull(); | |
| 6770 | 43 | return field->store_packed(nr); | |
| 6771 | } | ||
| 6772 | |||
| 6773 | 17740 | type_conversion_status Item_decimal::save_in_field_inner(Field *field, bool) { | |
| 6774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17740 times.
|
17740 | if (null_value) return set_field_to_null(field); |
| 6775 | |||
| 6776 | 17740 | field->set_notnull(); | |
| 6777 | 17740 | return field->store_decimal(&decimal_value); | |
| 6778 | } | ||
| 6779 | |||
| 6780 | 1035145 | bool Item_int::eq(const Item *arg, bool) const { | |
| 6781 | // No need to check for null value as integer constant can't be NULL | ||
| 6782 |
6/6✓ Branch 0 taken 324316 times.
✓ Branch 1 taken 710832 times.
✓ Branch 2 taken 324039 times.
✓ Branch 3 taken 278 times.
✓ Branch 4 taken 324039 times.
✓ Branch 5 taken 711110 times.
|
1035145 | if (arg->basic_const_item() && arg->type() == type()) { |
| 6783 | /* | ||
| 6784 | We need to cast off const to call val_int(). This should be OK for | ||
| 6785 | a basic constant. | ||
| 6786 | */ | ||
| 6787 | 324039 | Item *item = const_cast<Item *>(arg); | |
| 6788 |
3/4✓ Branch 0 taken 307809 times.
✓ Branch 1 taken 16230 times.
✓ Branch 2 taken 307809 times.
✗ Branch 3 not taken.
|
324039 | return item->val_int() == value && item->unsigned_flag == unsigned_flag; |
| 6789 | } | ||
| 6790 | 711110 | return false; | |
| 6791 | } | ||
| 6792 | |||
| 6793 | ✗ | Item *Item_int_with_ref::clone_item() const { | |
| 6794 | ✗ | assert(ref->const_item()); | |
| 6795 | /* | ||
| 6796 | We need to evaluate the constant to make sure it works with | ||
| 6797 | parameter markers. | ||
| 6798 | */ | ||
| 6799 | ✗ | return (ref->unsigned_flag | |
| 6800 | ✗ | ? new Item_uint(ref->item_name, ref->val_int(), ref->max_length) | |
| 6801 | ✗ | : new Item_int(ref->item_name, ref->val_int(), ref->max_length)); | |
| 6802 | } | ||
| 6803 | |||
| 6804 | ✗ | Item *Item_time_with_ref::clone_item() const { | |
| 6805 | ✗ | assert(ref->const_item()); | |
| 6806 | /* | ||
| 6807 | We need to evaluate the constant to make sure it works with | ||
| 6808 | parameter markers. | ||
| 6809 | */ | ||
| 6810 | ✗ | return new Item_temporal(MYSQL_TYPE_TIME, ref->item_name, | |
| 6811 | ✗ | ref->val_time_temporal(), ref->max_length); | |
| 6812 | } | ||
| 6813 | |||
| 6814 | ✗ | Item *Item_datetime_with_ref::clone_item() const { | |
| 6815 | ✗ | assert(ref->const_item()); | |
| 6816 | /* | ||
| 6817 | We need to evaluate the constant to make sure it works with | ||
| 6818 | parameter markers. | ||
| 6819 | */ | ||
| 6820 | ✗ | return new Item_temporal(MYSQL_TYPE_DATETIME, ref->item_name, | |
| 6821 | ✗ | ref->val_date_temporal(), ref->max_length); | |
| 6822 | } | ||
| 6823 | |||
| 6824 | 59 | void Item_temporal_with_ref::print(const THD *, String *str, | |
| 6825 | enum_query_type) const { | ||
| 6826 | char buff[MAX_DATE_STRING_REP_LENGTH]; | ||
| 6827 | MYSQL_TIME ltime; | ||
| 6828 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | TIME_from_longlong_packed(<ime, data_type(), value); |
| 6829 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | str->append("'"); |
| 6830 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | my_TIME_to_str(ltime, buff, decimals); |
| 6831 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | str->append(buff); |
| 6832 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | str->append('\''); |
| 6833 | 59 | } | |
| 6834 | |||
| 6835 | 1 | Item_num *Item_uint::neg() { | |
| 6836 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | Item_decimal *item = new Item_decimal(value, true); |
| 6837 | 1 | return item->neg(); | |
| 6838 | } | ||
| 6839 | |||
| 6840 | 18537 | static uint nr_of_decimals(const char *str, const char *end) { | |
| 6841 | const char *decimal_point; | ||
| 6842 | |||
| 6843 | /* Find position for '.' */ | ||
| 6844 | for (;;) { | ||
| 6845 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18534 times.
|
18537 | if (str == end) return 0; |
| 6846 |
4/4✓ Branch 0 taken 17978 times.
✓ Branch 1 taken 556 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 17896 times.
|
18534 | if (*str == 'e' || *str == 'E') return DECIMAL_NOT_SPECIFIED; |
| 6847 |
2/2✓ Branch 0 taken 4982 times.
✓ Branch 1 taken 12914 times.
|
17896 | if (*str++ == '.') break; |
| 6848 | } | ||
| 6849 | 4982 | decimal_point = str; | |
| 6850 |
4/4✓ Branch 0 taken 36562 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 31609 times.
✓ Branch 3 taken 4953 times.
|
36591 | for (; str < end && my_isdigit(system_charset_info, *str); str++) |
| 6851 | ; | ||
| 6852 |
6/6✓ Branch 0 taken 4953 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 1547 times.
✓ Branch 3 taken 3406 times.
✓ Branch 4 taken 1544 times.
✓ Branch 5 taken 3 times.
|
4982 | if (str < end && (*str == 'e' || *str == 'E')) return DECIMAL_NOT_SPECIFIED; |
| 6853 | /* | ||
| 6854 | QQ: | ||
| 6855 | The number of decimal digist in fact should be (str - decimal_point - 1). | ||
| 6856 | But it seems the result of nr_of_decimals() is never used! | ||
| 6857 | |||
| 6858 | In case of 'e' and 'E' nr_of_decimals returns DECIMAL_NOT_SPECIFIED. | ||
| 6859 | In case if there is no 'e' or 'E' parser code in sql_yacc.yy | ||
| 6860 | never calls Item_float::Item_float() - it creates Item_decimal instead. | ||
| 6861 | |||
| 6862 | The only piece of code where we call Item_float::Item_float(str, len) | ||
| 6863 | without having 'e' or 'E' is item_xmlfunc.cc, but this Item_float | ||
| 6864 | never appears in metadata itself. Changing the code to return | ||
| 6865 | (str - decimal_point - 1) does not make any changes in the test results. | ||
| 6866 | |||
| 6867 | This should be addressed somehow. | ||
| 6868 | Looks like a reminder from before real DECIMAL times. | ||
| 6869 | */ | ||
| 6870 | 32 | return (uint)(str - decimal_point); | |
| 6871 | } | ||
| 6872 | |||
| 6873 | /** | ||
| 6874 | This function is only called during parsing: | ||
| 6875 | - when parsing SQL query from sql_yacc.yy | ||
| 6876 | - when parsing XPath query from item_xmlfunc.cc | ||
| 6877 | We will signal an error if value is not a true double value (overflow): | ||
| 6878 | eng: Illegal %s '%-.192s' value found during parsing | ||
| 6879 | |||
| 6880 | Note: str_arg does not necessarily have to be a null terminated string, | ||
| 6881 | e.g. it is NOT when called from item_xmlfunc.cc or sql_yacc.yy. | ||
| 6882 | */ | ||
| 6883 | |||
| 6884 | 5623 | void Item_float::init(const char *str_arg, uint length) { | |
| 6885 | int error; | ||
| 6886 | const char *end_not_used; | ||
| 6887 |
1/2✓ Branch 0 taken 5623 times.
✗ Branch 1 not taken.
|
5623 | value = my_strntod(&my_charset_bin, str_arg, length, &end_not_used, &error); |
| 6888 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5617 times.
|
5623 | if (error) { |
| 6889 | char tmp[NAME_LEN + 1]; | ||
| 6890 | 6 | snprintf(tmp, sizeof(tmp), "%.*s", length, str_arg); | |
| 6891 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp); |
| 6892 | } | ||
| 6893 |
1/2✓ Branch 0 taken 5623 times.
✗ Branch 1 not taken.
|
5623 | presentation.copy(str_arg, length); |
| 6894 |
1/2✓ Branch 0 taken 5623 times.
✗ Branch 1 not taken.
|
5623 | item_name.copy(str_arg, length); |
| 6895 | 5623 | set_data_type(MYSQL_TYPE_DOUBLE); | |
| 6896 | 5623 | decimals = (uint8)nr_of_decimals(str_arg, str_arg + length); | |
| 6897 | 5623 | max_length = length; | |
| 6898 | 5623 | fixed = true; | |
| 6899 | 5623 | } | |
| 6900 | |||
| 6901 | 2982 | type_conversion_status Item_float::save_in_field_inner(Field *field, bool) { | |
| 6902 | 2982 | double nr = val_real(); | |
| 6903 | // TODO: call set_field_to_null_with_conversions below | ||
| 6904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2982 times.
|
2982 | if (null_value) return set_field_to_null(field); |
| 6905 | 2982 | field->set_notnull(); | |
| 6906 | 2982 | return field->store(nr); | |
| 6907 | } | ||
| 6908 | |||
| 6909 | 772 | void Item_float::print(const THD *, String *str, | |
| 6910 | enum_query_type query_type) const { | ||
| 6911 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 772 times.
|
772 | if (query_type & QT_NORMALIZED_FORMAT) { |
| 6912 | ✗ | str->append("?"); | |
| 6913 | 320 | return; | |
| 6914 | } | ||
| 6915 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 452 times.
|
772 | if (presentation.ptr()) { |
| 6916 |
1/2✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
|
320 | str->append(presentation.ptr()); |
| 6917 | 320 | return; | |
| 6918 | } | ||
| 6919 | char buffer[20]; | ||
| 6920 | 452 | String num(buffer, sizeof(buffer), &my_charset_bin); | |
| 6921 |
1/2✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
|
452 | num.set_real(value, decimals, &my_charset_bin); |
| 6922 |
1/2✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
|
452 | str->append(num); |
| 6923 | 452 | } | |
| 6924 | |||
| 6925 | /* | ||
| 6926 | hex item | ||
| 6927 | In string context this is a binary string. | ||
| 6928 | In number context this is a longlong value. | ||
| 6929 | */ | ||
| 6930 | |||
| 6931 | 821 | bool Item_float::eq(const Item *arg, bool) const { | |
| 6932 |
5/6✓ Branch 0 taken 36 times.
✓ Branch 1 taken 785 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 785 times.
|
821 | if (arg->basic_const_item() && arg->type() == type()) { |
| 6933 | /* | ||
| 6934 | We need to cast off const to call val_int(). This should be OK for | ||
| 6935 | a basic constant. | ||
| 6936 | */ | ||
| 6937 | 36 | Item *item = const_cast<Item *>(arg); | |
| 6938 | 36 | return item->val_real() == value; | |
| 6939 | } | ||
| 6940 | 785 | return false; | |
| 6941 | } | ||
| 6942 | |||
| 6943 | 199477 | inline uint char_val(char X) { | |
| 6944 |
4/6✓ Branch 0 taken 199477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 130322 times.
✓ Branch 3 taken 69155 times.
✓ Branch 4 taken 69155 times.
✗ Branch 5 not taken.
|
268632 | return (uint)(X >= '0' && X <= '9' |
| 6945 | 130322 | ? X - '0' | |
| 6946 |
2/2✓ Branch 0 taken 55900 times.
✓ Branch 1 taken 13255 times.
|
268632 | : X >= 'A' && X <= 'Z' ? X - 'A' + 10 : X - 'a' + 10); |
| 6947 | } | ||
| 6948 | |||
| 6949 | ✗ | Item_hex_string::Item_hex_string() { hex_string_init("", 0); } | |
| 6950 | |||
| 6951 | 1 | Item_hex_string::Item_hex_string(const char *str, uint str_length) { | |
| 6952 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | hex_string_init(str, str_length); |
| 6953 | 1 | } | |
| 6954 | |||
| 6955 | 20317 | Item_hex_string::Item_hex_string(const POS &pos, const LEX_STRING &literal) | |
| 6956 | 20317 | : super(pos) { | |
| 6957 |
1/2✓ Branch 0 taken 20317 times.
✗ Branch 1 not taken.
|
20317 | hex_string_init(literal.str, literal.length); |
| 6958 | 20317 | } | |
| 6959 | |||
| 6960 | 31941 | LEX_CSTRING Item_hex_string::make_hex_str(const char *str, size_t str_length) { | |
| 6961 | 31941 | size_t max_length = (str_length + 1) / 2; | |
| 6962 |
2/4✓ Branch 0 taken 31941 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31941 times.
✗ Branch 3 not taken.
|
31941 | char *ptr = (char *)(*THR_MALLOC)->Alloc(max_length + 1); |
| 6963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31941 times.
|
31941 | if (ptr == nullptr) return NULL_CSTR; |
| 6964 | 31941 | LEX_CSTRING ret = {ptr, max_length}; | |
| 6965 | 31941 | char *end = ptr + max_length; | |
| 6966 |
2/2✓ Branch 0 taken 841 times.
✓ Branch 1 taken 31100 times.
|
31941 | if (max_length * 2 != str_length) |
| 6967 | 841 | *ptr++ = char_val(*str++); // Not even, assume 0 prefix | |
| 6968 |
2/2✓ Branch 0 taken 99318 times.
✓ Branch 1 taken 31941 times.
|
131259 | while (ptr != end) { |
| 6969 | 99318 | *ptr++ = (char)(char_val(str[0]) * 16 + char_val(str[1])); | |
| 6970 | 99318 | str += 2; | |
| 6971 | } | ||
| 6972 | 31941 | *ptr = 0; // needed if printed in error message | |
| 6973 | 31941 | return ret; | |
| 6974 | } | ||
| 6975 | |||
| 6976 | 241 | uint Item_hex_string::decimal_precision() const { | |
| 6977 |
5/9✗ Branch 0 not taken.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 7 times.
|
241 | switch (max_length) { |
| 6978 | ✗ | case 0: | |
| 6979 | ✗ | return count_digits(0U); | |
| 6980 | 205 | case 1: | |
| 6981 | 205 | return count_digits(0xFFU); | |
| 6982 | 14 | case 2: | |
| 6983 | 14 | return count_digits(0xFFFFU); | |
| 6984 | ✗ | case 3: | |
| 6985 | ✗ | return count_digits(0xFFFFFFU); | |
| 6986 | 7 | case 4: | |
| 6987 | 7 | return count_digits(0xFFFFFFFFU); | |
| 6988 | ✗ | case 5: | |
| 6989 | ✗ | return count_digits(0xFFFFFFFFFFU); | |
| 6990 | ✗ | case 6: | |
| 6991 | ✗ | return count_digits(0xFFFFFFFFFFFFU); | |
| 6992 | 8 | case 7: | |
| 6993 | 8 | return count_digits(0xFFFFFFFFFFFFFFU); | |
| 6994 | 7 | default: | |
| 6995 | // val_int() and val_decimal() look at the first eight bytes. Longer | ||
| 6996 | // values are truncated. | ||
| 6997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(max_length >= 8); |
| 6998 | 7 | return count_digits(0xFFFFFFFFFFFFFFFFU); | |
| 6999 | } | ||
| 7000 | } | ||
| 7001 | |||
| 7002 | 20318 | void Item_hex_string::hex_string_init(const char *str, uint str_length) { | |
| 7003 |
1/2✓ Branch 0 taken 20318 times.
✗ Branch 1 not taken.
|
20318 | LEX_CSTRING s = make_hex_str(str, str_length); |
| 7004 |
1/2✓ Branch 0 taken 20318 times.
✗ Branch 1 not taken.
|
20318 | str_value.set(s.str, s.length, &my_charset_bin); |
| 7005 | 20318 | set_data_type(MYSQL_TYPE_VARCHAR); | |
| 7006 | 20318 | max_length = s.length; | |
| 7007 | 20318 | collation.set(&my_charset_bin, DERIVATION_COERCIBLE); | |
| 7008 | 20318 | fixed = true; | |
| 7009 | 20318 | unsigned_flag = true; | |
| 7010 | 20318 | } | |
| 7011 | |||
| 7012 | 11851 | longlong Item_hex_string::val_int() { | |
| 7013 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 7014 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11851 times.
|
11851 | assert(fixed == 1); |
| 7015 | 11851 | const char *end = str_value.ptr() + str_value.length(); | |
| 7016 | const char *ptr; | ||
| 7017 | |||
| 7018 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11839 times.
|
11851 | if (str_value.length() > sizeof(longlong)) { |
| 7019 | /* | ||
| 7020 | Too many bytes for longlong; lost bytes are [start, lost_end[ ; there is | ||
| 7021 | no loss of data in conversion only if they are all zeroes. | ||
| 7022 | */ | ||
| 7023 | 12 | const char *lost_end = end - sizeof(longlong); | |
| 7024 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | for (ptr = str_value.ptr(); ptr < lost_end; ++ptr) |
| 7025 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (*ptr != 0) { |
| 7026 | // Human-readable, size-limited printout of the hex: | ||
| 7027 | 12 | char errbuff[MYSQL_ERRMSG_SIZE], *errptr = errbuff; | |
| 7028 | 12 | *errptr++ = 'x'; | |
| 7029 | 12 | *errptr++ = '\''; | |
| 7030 |
2/2✓ Branch 0 taken 273 times.
✓ Branch 1 taken 12 times.
|
285 | for (ptr = str_value.ptr(); ptr < end; ++ptr) { |
| 7031 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
|
273 | if (errptr > errbuff + sizeof(errbuff) - 4) break; |
| 7032 | 273 | *errptr++ = _dig_vec_lower[((uchar)*ptr) >> 4]; | |
| 7033 | 273 | *errptr++ = _dig_vec_lower[((uchar)*ptr) & 0x0F]; | |
| 7034 | } | ||
| 7035 | 12 | *errptr++ = '\''; | |
| 7036 | 12 | *errptr++ = 0; | |
| 7037 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | THD *thd = current_thd; |
| 7038 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | push_warning_printf( |
| 7039 | thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE, | ||
| 7040 | ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "BINARY", errbuff); | ||
| 7041 | 12 | return 0; | |
| 7042 | } | ||
| 7043 | } | ||
| 7044 | |||
| 7045 | 11839 | ptr = end - str_value.length(); | |
| 7046 | 11839 | ulonglong value = 0; | |
| 7047 |
2/2✓ Branch 0 taken 25461 times.
✓ Branch 1 taken 11839 times.
|
37300 | for (; ptr != end; ptr++) value = (value << 8) + (ulonglong)(uchar)*ptr; |
| 7048 | 11839 | return (longlong)value; | |
| 7049 | } | ||
| 7050 | |||
| 7051 | 53 | my_decimal *Item_hex_string::val_decimal(my_decimal *decimal_value) { | |
| 7052 | // following assert is redundant, because fixed=1 assigned in constructor | ||
| 7053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | assert(fixed == 1); |
| 7054 | 53 | ulonglong value = (ulonglong)val_int(); | |
| 7055 | 53 | int2my_decimal(E_DEC_FATAL_ERROR, value, true, decimal_value); | |
| 7056 | 53 | return (decimal_value); | |
| 7057 | } | ||
| 7058 | |||
| 7059 | 23938 | type_conversion_status Item_hex_string::save_in_field_inner(Field *field, | |
| 7060 | bool) { | ||
| 7061 | 23938 | field->set_notnull(); | |
| 7062 |
2/2✓ Branch 0 taken 17306 times.
✓ Branch 1 taken 6632 times.
|
23938 | if (field->result_type() == STRING_RESULT) |
| 7063 | 17306 | return field->store(str_value.ptr(), str_value.length(), | |
| 7064 | 17306 | collation.collation); | |
| 7065 | |||
| 7066 | ulonglong nr; | ||
| 7067 | 6632 | size_t length = str_value.length(); | |
| 7068 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6628 times.
|
6632 | if (!length) { |
| 7069 | 4 | field->reset(); | |
| 7070 | 4 | return TYPE_WARN_OUT_OF_RANGE; | |
| 7071 | } | ||
| 7072 |
2/2✓ Branch 0 taken 678 times.
✓ Branch 1 taken 5950 times.
|
6628 | if (length > 8) { |
| 7073 |
2/2✓ Branch 0 taken 660 times.
✓ Branch 1 taken 18 times.
|
678 | nr = field->is_flag_set(UNSIGNED_FLAG) ? ULLONG_MAX : LLONG_MAX; |
| 7074 | 678 | goto warn; | |
| 7075 | } | ||
| 7076 | 5950 | nr = (ulonglong)val_int(); | |
| 7077 |
8/8✓ Branch 0 taken 606 times.
✓ Branch 1 taken 5344 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 545 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 48 times.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 5937 times.
|
5950 | if ((length == 8) && !field->is_flag_set(UNSIGNED_FLAG) && (nr > LLONG_MAX)) { |
| 7078 | 13 | nr = LLONG_MAX; | |
| 7079 | 13 | goto warn; | |
| 7080 | } | ||
| 7081 | 5937 | return field->store((longlong)nr, true); // Assume hex numbers are unsigned | |
| 7082 | |||
| 7083 | 691 | warn: | |
| 7084 | 691 | const type_conversion_status res = field->store((longlong)nr, true); | |
| 7085 |
2/2✓ Branch 0 taken 59 times.
✓ Branch 1 taken 632 times.
|
691 | if (res == TYPE_OK) |
| 7086 | 59 | field->set_warning(Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, 1); | |
| 7087 | 691 | return res; | |
| 7088 | } | ||
| 7089 | |||
| 7090 | 140 | void Item_hex_string::print(const THD *, String *str, | |
| 7091 | enum_query_type query_type) const { | ||
| 7092 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 138 times.
|
140 | if (query_type & QT_NORMALIZED_FORMAT) { |
| 7093 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | str->append("?"); |
| 7094 | 2 | return; | |
| 7095 | } | ||
| 7096 | 138 | const uchar *ptr = pointer_cast<const uchar *>(str_value.ptr()); | |
| 7097 | 138 | const uchar *end = ptr + str_value.length(); | |
| 7098 |
1/2✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
|
138 | str->append("0x"); |
| 7099 |
2/2✓ Branch 0 taken 942 times.
✓ Branch 1 taken 138 times.
|
1080 | for (; ptr != end; ptr++) { |
| 7100 | 942 | str->append(_dig_vec_lower[*ptr >> 4]); | |
| 7101 | 942 | str->append(_dig_vec_lower[*ptr & 0x0F]); | |
| 7102 | } | ||
| 7103 | } | ||
| 7104 | |||
| 7105 | 561 | bool Item_hex_string::eq(const Item *item, bool binary_cmp) const { | |
| 7106 |
5/6✓ Branch 0 taken 34 times.
✓ Branch 1 taken 527 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 527 times.
|
561 | if (item->basic_const_item() && item->type() == type()) { |
| 7107 | // Should be OK for a basic constant. | ||
| 7108 | 34 | Item *arg = const_cast<Item *>(item); | |
| 7109 | 34 | String str; | |
| 7110 |
3/6✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
|
34 | if (binary_cmp) return !stringcmp(&str_value, arg->val_str(&str)); |
| 7111 | ✗ | return !sortcmp(&str_value, arg->val_str(&str), collation.collation); | |
| 7112 | 34 | } | |
| 7113 | 527 | return false; | |
| 7114 | } | ||
| 7115 | |||
| 7116 | 79 | Item *Item_hex_string::safe_charset_converter(THD *, const CHARSET_INFO *tocs) { | |
| 7117 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | String tmp, *str = val_str(&tmp); |
| 7118 | |||
| 7119 |
2/4✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
|
79 | auto conv = new Item_string(str->ptr(), str->length(), tocs); |
| 7120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | if (conv == nullptr) return nullptr; |
| 7121 | 79 | conv->mark_result_as_const(); | |
| 7122 | 79 | return conv; | |
| 7123 | 79 | } | |
| 7124 | |||
| 7125 | /* | ||
| 7126 | bin item. | ||
| 7127 | In string context this is a binary string. | ||
| 7128 | In number context this is a longlong value. | ||
| 7129 | */ | ||
| 7130 | |||
| 7131 | 6356 | LEX_CSTRING Item_bin_string::make_bin_str(const char *str, size_t str_length) { | |
| 7132 | 6356 | const char *end = str + str_length - 1; | |
| 7133 | 6356 | uchar bits = 0; | |
| 7134 | 6356 | uint power = 1; | |
| 7135 | |||
| 7136 | 6356 | size_t max_length = (str_length + 7) >> 3; | |
| 7137 |
2/4✓ Branch 0 taken 6356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6356 times.
✗ Branch 3 not taken.
|
6356 | char *ptr = (char *)(*THR_MALLOC)->Alloc(max_length + 1); |
| 7138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6356 times.
|
6356 | if (ptr == nullptr) return NULL_CSTR; |
| 7139 | |||
| 7140 | 6356 | LEX_CSTRING ret{ptr, max_length}; | |
| 7141 | |||
| 7142 |
2/2✓ Branch 0 taken 6352 times.
✓ Branch 1 taken 4 times.
|
6356 | if (max_length > 0) { |
| 7143 | 6352 | ptr += max_length - 1; | |
| 7144 | 6352 | ptr[1] = 0; // Set end null for string | |
| 7145 |
2/2✓ Branch 0 taken 119527 times.
✓ Branch 1 taken 6352 times.
|
125879 | for (; end >= str; end--) { |
| 7146 |
2/2✓ Branch 0 taken 11467 times.
✓ Branch 1 taken 108060 times.
|
119527 | if (power == 256) { |
| 7147 | 11467 | power = 1; | |
| 7148 | 11467 | *ptr-- = bits; | |
| 7149 | 11467 | bits = 0; | |
| 7150 | } | ||
| 7151 |
2/2✓ Branch 0 taken 62655 times.
✓ Branch 1 taken 56872 times.
|
119527 | if (*end == '1') bits |= power; |
| 7152 | 119527 | power <<= 1; | |
| 7153 | } | ||
| 7154 | 6352 | *ptr = (char)bits; | |
| 7155 | } else | ||
| 7156 | 4 | ptr[0] = 0; | |
| 7157 | |||
| 7158 | 6356 | return ret; | |
| 7159 | } | ||
| 7160 | |||
| 7161 | 6338 | void Item_bin_string::bin_string_init(const char *str, size_t str_length) { | |
| 7162 |
1/2✓ Branch 0 taken 6338 times.
✗ Branch 1 not taken.
|
6338 | LEX_CSTRING s = make_bin_str(str, str_length); |
| 7163 | 6338 | max_length = s.length; | |
| 7164 |
1/2✓ Branch 0 taken 6338 times.
✗ Branch 1 not taken.
|
6338 | str_value.set(s.str, s.length, &my_charset_bin); |
| 7165 | 6338 | collation.set(&my_charset_bin, DERIVATION_COERCIBLE); | |
| 7166 | 6338 | fixed = true; | |
| 7167 | 6338 | } | |
| 7168 | |||
| 7169 | /** | ||
| 7170 | Pack data in buffer for sending. | ||
| 7171 | */ | ||
| 7172 | |||
| 7173 | 3612559 | bool Item_null::send(Protocol *protocol, String *) { | |
| 7174 | 3612559 | return protocol->store_null(); | |
| 7175 | } | ||
| 7176 | |||
| 7177 | 706 | Item_json::Item_json(unique_ptr_destroy_only<Json_wrapper> value, | |
| 7178 | 706 | const Item_name_string &name) | |
| 7179 | 706 | : m_value(std::move(value)) { | |
| 7180 | 706 | set_data_type_json(); | |
| 7181 | 706 | item_name = name; | |
| 7182 | 706 | } | |
| 7183 | |||
| 7184 | 2824 | Item_json::~Item_json() = default; | |
| 7185 | |||
| 7186 | 175 | void Item_json::print(const THD *, String *str, enum_query_type) const { | |
| 7187 |
1/2✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
|
175 | str->append("json'"); |
| 7188 |
1/2✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
|
175 | m_value->to_string(str, true, "", JsonDocumentDefaultDepthHandler); |
| 7189 |
1/2✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
|
175 | str->append("'"); |
| 7190 | 175 | } | |
| 7191 | |||
| 7192 | 2136 | bool Item_json::val_json(Json_wrapper *result) { | |
| 7193 | 2136 | *result = *m_value; | |
| 7194 | 2136 | return false; | |
| 7195 | } | ||
| 7196 | |||
| 7197 | /* | ||
| 7198 | The functions below are rarely called, some of them are probably unreachable | ||
| 7199 | from SQL, because Item_json is used in a more limited way than other | ||
| 7200 | subclasses of Item_basic_constant. Most notably, there is no JSON literal | ||
| 7201 | syntax which gets translated into Item_json objects by the parser. | ||
| 7202 | */ | ||
| 7203 | |||
| 7204 | 3 | double Item_json::val_real() { return m_value->coerce_real(item_name.ptr()); } | |
| 7205 | |||
| 7206 | 6 | longlong Item_json::val_int() { return m_value->coerce_int(item_name.ptr()); } | |
| 7207 | |||
| 7208 | 4 | String *Item_json::val_str(String *str) { | |
| 7209 | 4 | str->length(0); | |
| 7210 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (m_value->to_string(str, true, item_name.ptr(), |
| 7211 | JsonDocumentDefaultDepthHandler)) | ||
| 7212 | ✗ | return error_str(); | |
| 7213 | 4 | return str; | |
| 7214 | } | ||
| 7215 | |||
| 7216 | 3 | my_decimal *Item_json::val_decimal(my_decimal *buf) { | |
| 7217 | 3 | return m_value->coerce_decimal(buf, item_name.ptr()); | |
| 7218 | } | ||
| 7219 | |||
| 7220 | 3 | bool Item_json::get_date(MYSQL_TIME *ltime, my_time_flags_t) { | |
| 7221 | 3 | return m_value->coerce_date(ltime, item_name.ptr()); | |
| 7222 | } | ||
| 7223 | |||
| 7224 | 3 | bool Item_json::get_time(MYSQL_TIME *ltime) { | |
| 7225 | 3 | return m_value->coerce_time(ltime, item_name.ptr()); | |
| 7226 | } | ||
| 7227 | |||
| 7228 | 3 | Item *Item_json::clone_item() const { | |
| 7229 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | THD *const thd = current_thd; |
| 7230 | auto wr = make_unique_destroy_only<Json_wrapper>(thd->mem_root, | ||
| 7231 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | m_value->clone_dom()); |
| 7232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (wr == nullptr) return nullptr; |
| 7233 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return new Item_json(std::move(wr), item_name); |
| 7234 | 3 | } | |
| 7235 | |||
| 7236 | /** | ||
| 7237 | This is only called from items that is not of type item_field. | ||
| 7238 | */ | ||
| 7239 | |||
| 7240 | 15113894 | bool Item::send(Protocol *protocol, String *buffer) { | |
| 7241 |
10/10✓ Branch 0 taken 12203069 times.
✓ Branch 1 taken 393 times.
✓ Branch 2 taken 474 times.
✓ Branch 3 taken 72839 times.
✓ Branch 4 taken 2550590 times.
✓ Branch 5 taken 217 times.
✓ Branch 6 taken 110956 times.
✓ Branch 7 taken 625 times.
✓ Branch 8 taken 173598 times.
✓ Branch 9 taken 1141 times.
|
15113894 | switch (data_type()) { |
| 7242 | 12203069 | default: | |
| 7243 | case MYSQL_TYPE_NULL: | ||
| 7244 | case MYSQL_TYPE_BOOL: | ||
| 7245 | case MYSQL_TYPE_INVALID: | ||
| 7246 | case MYSQL_TYPE_DECIMAL: | ||
| 7247 | case MYSQL_TYPE_ENUM: | ||
| 7248 | case MYSQL_TYPE_SET: | ||
| 7249 | case MYSQL_TYPE_TINY_BLOB: | ||
| 7250 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 7251 | case MYSQL_TYPE_LONG_BLOB: | ||
| 7252 | case MYSQL_TYPE_BLOB: | ||
| 7253 | case MYSQL_TYPE_GEOMETRY: | ||
| 7254 | case MYSQL_TYPE_STRING: | ||
| 7255 | case MYSQL_TYPE_VAR_STRING: | ||
| 7256 | case MYSQL_TYPE_VARCHAR: | ||
| 7257 | case MYSQL_TYPE_BIT: | ||
| 7258 | case MYSQL_TYPE_NEWDECIMAL: | ||
| 7259 | case MYSQL_TYPE_JSON: { | ||
| 7260 | 12203069 | const String *res = val_str(buffer); | |
| 7261 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12203067 times.
|
12203068 | assert(null_value == (res == nullptr)); |
| 7262 |
2/2✓ Branch 0 taken 12095008 times.
✓ Branch 1 taken 108059 times.
|
12203067 | if (res != nullptr) |
| 7263 | 12095008 | return protocol->store_string(res->ptr(), res->length(), | |
| 7264 | 12095011 | res->charset()); | |
| 7265 | 108059 | break; | |
| 7266 | } | ||
| 7267 | 393 | case MYSQL_TYPE_TINY: { | |
| 7268 | 393 | longlong nr = val_int(); | |
| 7269 |
2/2✓ Branch 0 taken 225 times.
✓ Branch 1 taken 168 times.
|
393 | if (!null_value) return protocol->store_tiny(nr); |
| 7270 | 168 | break; | |
| 7271 | } | ||
| 7272 | 474 | case MYSQL_TYPE_SHORT: | |
| 7273 | case MYSQL_TYPE_YEAR: { | ||
| 7274 | 474 | longlong nr = val_int(); | |
| 7275 |
2/2✓ Branch 0 taken 286 times.
✓ Branch 1 taken 188 times.
|
474 | if (!null_value) return protocol->store_short(nr); |
| 7276 | 188 | break; | |
| 7277 | } | ||
| 7278 | 72839 | case MYSQL_TYPE_INT24: | |
| 7279 | case MYSQL_TYPE_LONG: { | ||
| 7280 | 72839 | longlong nr = val_int(); | |
| 7281 |
2/2✓ Branch 0 taken 47765 times.
✓ Branch 1 taken 25074 times.
|
72839 | if (!null_value) return protocol->store_long(nr); |
| 7282 | 25074 | break; | |
| 7283 | } | ||
| 7284 | 2550590 | case MYSQL_TYPE_LONGLONG: { | |
| 7285 | 2550590 | longlong nr = val_int(); | |
| 7286 |
2/2✓ Branch 0 taken 2198638 times.
✓ Branch 1 taken 351926 times.
|
2550564 | if (!null_value) return protocol->store_longlong(nr, unsigned_flag); |
| 7287 | 351926 | break; | |
| 7288 | } | ||
| 7289 | 217 | case MYSQL_TYPE_FLOAT: { | |
| 7290 | 217 | float nr = static_cast<float>(val_real()); | |
| 7291 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 145 times.
|
217 | if (!null_value) return protocol->store_float(nr, decimals, 0); |
| 7292 | 145 | break; | |
| 7293 | } | ||
| 7294 | 110956 | case MYSQL_TYPE_DOUBLE: { | |
| 7295 | 110956 | double nr = val_real(); | |
| 7296 |
2/2✓ Branch 0 taken 105476 times.
✓ Branch 1 taken 5480 times.
|
110956 | if (!null_value) return protocol->store_double(nr, decimals, 0); |
| 7297 | 5480 | break; | |
| 7298 | } | ||
| 7299 | 625 | case MYSQL_TYPE_DATE: { | |
| 7300 | MYSQL_TIME tm; | ||
| 7301 |
1/2✓ Branch 0 taken 625 times.
✗ Branch 1 not taken.
|
625 | get_date(&tm, TIME_FUZZY_DATE); |
| 7302 |
3/4✓ Branch 0 taken 366 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 366 times.
✗ Branch 3 not taken.
|
625 | if (!null_value) return protocol->store_date(tm); |
| 7303 | 259 | break; | |
| 7304 | } | ||
| 7305 | 173598 | case MYSQL_TYPE_DATETIME: | |
| 7306 | case MYSQL_TYPE_TIMESTAMP: { | ||
| 7307 | MYSQL_TIME tm; | ||
| 7308 |
1/2✓ Branch 0 taken 173598 times.
✗ Branch 1 not taken.
|
173598 | get_date(&tm, TIME_FUZZY_DATE); |
| 7309 |
3/4✓ Branch 0 taken 26610 times.
✓ Branch 1 taken 146988 times.
✓ Branch 2 taken 26610 times.
✗ Branch 3 not taken.
|
173598 | if (!null_value) return protocol->store_datetime(tm, decimals); |
| 7310 | 146988 | break; | |
| 7311 | } | ||
| 7312 | 1141 | case MYSQL_TYPE_TIME: { | |
| 7313 | MYSQL_TIME tm; | ||
| 7314 |
1/2✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
|
1141 | get_time(&tm); |
| 7315 |
3/4✓ Branch 0 taken 917 times.
✓ Branch 1 taken 222 times.
✓ Branch 2 taken 917 times.
✗ Branch 3 not taken.
|
1139 | if (!null_value) return protocol->store_time(tm, decimals); |
| 7316 | 222 | break; | |
| 7317 | } | ||
| 7318 | } | ||
| 7319 | |||
| 7320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 638509 times.
|
638509 | assert(null_value); |
| 7321 | 638509 | return protocol->store_null(); | |
| 7322 | } | ||
| 7323 | |||
| 7324 | 16897041 | bool Item::update_null_value() { | |
| 7325 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 7326 | 16897041 | String str(buff, sizeof(buff), collation.collation); | |
| 7327 |
2/4✓ Branch 0 taken 16897041 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16897041 times.
✗ Branch 3 not taken.
|
33794082 | return evaluate(current_thd, &str); |
| 7328 | 16897041 | } | |
| 7329 | |||
| 7330 | /** | ||
| 7331 | Evaluate item, possibly using the supplied buffer | ||
| 7332 | |||
| 7333 | @param thd Thread context | ||
| 7334 | @param buffer Buffer, in case item needs a large one | ||
| 7335 | |||
| 7336 | @returns false if success, true if error | ||
| 7337 | */ | ||
| 7338 | |||
| 7339 | 16910977 | bool Item::evaluate(THD *thd, String *buffer) { | |
| 7340 |
7/8✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
✓ Branch 2 taken 31058 times.
✓ Branch 3 taken 16860162 times.
✓ Branch 4 taken 3471 times.
✓ Branch 5 taken 8015 times.
✓ Branch 6 taken 7598 times.
✓ Branch 7 taken 216 times.
|
16910977 | switch (data_type()) { |
| 7341 | ✗ | case MYSQL_TYPE_INVALID: | |
| 7342 | default: | ||
| 7343 | ✗ | assert(false); | |
| 7344 | (void)val_str(buffer); | ||
| 7345 | break; | ||
| 7346 | 457 | case MYSQL_TYPE_JSON: { | |
| 7347 | 457 | Json_wrapper wr; | |
| 7348 |
1/2✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
|
457 | (void)val_json(&wr); |
| 7349 | 457 | } break; | |
| 7350 | 31058 | case MYSQL_TYPE_NULL: | |
| 7351 | case MYSQL_TYPE_DECIMAL: | ||
| 7352 | case MYSQL_TYPE_ENUM: | ||
| 7353 | case MYSQL_TYPE_SET: | ||
| 7354 | case MYSQL_TYPE_TINY_BLOB: | ||
| 7355 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 7356 | case MYSQL_TYPE_LONG_BLOB: | ||
| 7357 | case MYSQL_TYPE_BLOB: | ||
| 7358 | case MYSQL_TYPE_GEOMETRY: | ||
| 7359 | case MYSQL_TYPE_STRING: | ||
| 7360 | case MYSQL_TYPE_VAR_STRING: | ||
| 7361 | case MYSQL_TYPE_VARCHAR: | ||
| 7362 | case MYSQL_TYPE_BIT: { | ||
| 7363 | 31058 | (void)val_str(buffer); | |
| 7364 | 31058 | break; | |
| 7365 | } | ||
| 7366 | 16860162 | case MYSQL_TYPE_BOOL: | |
| 7367 | case MYSQL_TYPE_TINY: | ||
| 7368 | case MYSQL_TYPE_SHORT: | ||
| 7369 | case MYSQL_TYPE_YEAR: | ||
| 7370 | case MYSQL_TYPE_INT24: | ||
| 7371 | case MYSQL_TYPE_LONG: | ||
| 7372 | case MYSQL_TYPE_LONGLONG: { | ||
| 7373 | 16860162 | (void)val_int(); | |
| 7374 | 16860164 | break; | |
| 7375 | } | ||
| 7376 | 3471 | case MYSQL_TYPE_NEWDECIMAL: { | |
| 7377 | 3471 | my_decimal decimal_value; | |
| 7378 |
1/2✓ Branch 0 taken 3471 times.
✗ Branch 1 not taken.
|
3471 | (void)val_decimal(&decimal_value); |
| 7379 | 3471 | break; | |
| 7380 | 3471 | } | |
| 7381 | |||
| 7382 | 8015 | case MYSQL_TYPE_FLOAT: | |
| 7383 | case MYSQL_TYPE_DOUBLE: { | ||
| 7384 | 8015 | (void)val_real(); | |
| 7385 | 8015 | break; | |
| 7386 | } | ||
| 7387 | 7598 | case MYSQL_TYPE_DATETIME: | |
| 7388 | case MYSQL_TYPE_DATE: | ||
| 7389 | case MYSQL_TYPE_TIMESTAMP: { | ||
| 7390 | MYSQL_TIME tm; | ||
| 7391 |
1/2✓ Branch 0 taken 7598 times.
✗ Branch 1 not taken.
|
7598 | (void)get_date(&tm, TIME_FUZZY_DATE); |
| 7392 | 7598 | break; | |
| 7393 | } | ||
| 7394 | 216 | case MYSQL_TYPE_TIME: { | |
| 7395 | MYSQL_TIME tm; | ||
| 7396 |
1/2✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
|
216 | (void)get_time(&tm); |
| 7397 | 214 | break; | |
| 7398 | } | ||
| 7399 | } | ||
| 7400 | 16910977 | const bool result = thd->is_error(); | |
| 7401 | // Convention: set NULL value indicator on error | ||
| 7402 |
2/2✓ Branch 0 taken 831 times.
✓ Branch 1 taken 16910146 times.
|
16910977 | if (result) null_value = true; |
| 7403 | 16910977 | return result; | |
| 7404 | } | ||
| 7405 | |||
| 7406 | /** | ||
| 7407 | Check if an item is a constant one and can be cached. | ||
| 7408 | |||
| 7409 | @param [out] arg If != NULL <=> Cache this item. | ||
| 7410 | |||
| 7411 | @return true Go deeper in item tree. | ||
| 7412 | @return false Don't go deeper in item tree. | ||
| 7413 | */ | ||
| 7414 | |||
| 7415 | 10993529 | bool Item::cache_const_expr_analyzer(uchar **arg) { | |
| 7416 | 10993529 | cache_const_expr_arg *carg = (cache_const_expr_arg *)*arg; | |
| 7417 |
2/2✓ Branch 0 taken 10979642 times.
✓ Branch 1 taken 13887 times.
|
10993529 | if (!carg->cache_item) { |
| 7418 | 10979642 | Item *item = real_item(); | |
| 7419 | /* | ||
| 7420 | Cache constant items unless it's a basic constant, a constant field, | ||
| 7421 | a subquery (they use their own cache), | ||
| 7422 | a ROW object (rollback logic can get messy), | ||
| 7423 | or it is already cached. | ||
| 7424 | */ | ||
| 7425 |
4/4✓ Branch 0 taken 2728665 times.
✓ Branch 1 taken 8250986 times.
✓ Branch 2 taken 145586 times.
✓ Branch 3 taken 10834050 times.
|
13708301 | if (const_for_execution() && |
| 7426 |
3/4✓ Branch 0 taken 149985 times.
✓ Branch 1 taken 2578675 times.
✓ Branch 2 taken 149985 times.
✗ Branch 3 not taken.
|
2728665 | !(basic_const_item() || item->basic_const_item() || |
| 7427 |
4/4✓ Branch 0 taken 149454 times.
✓ Branch 1 taken 531 times.
✓ Branch 2 taken 147490 times.
✓ Branch 3 taken 1964 times.
|
149985 | item->type() == Item::FIELD_ITEM || item->type() == SUBSELECT_ITEM || |
| 7428 |
4/4✓ Branch 0 taken 147088 times.
✓ Branch 1 taken 402 times.
✓ Branch 2 taken 147075 times.
✓ Branch 3 taken 13 times.
|
147490 | item->type() == ROW_ITEM || item->type() == CACHE_ITEM || |
| 7429 |
2/2✓ Branch 0 taken 145586 times.
✓ Branch 1 taken 1479 times.
|
147075 | item->type() == PARAM_ITEM)) |
| 7430 | /* | ||
| 7431 | Note that we use cache_item as a flag (NULL vs non-NULL), but we | ||
| 7432 | are storing the pointer so that we can assert that we cache the | ||
| 7433 | correct item in Item::cache_const_expr_transformer(). | ||
| 7434 | */ | ||
| 7435 | 145586 | carg->cache_item = this; | |
| 7436 | /* | ||
| 7437 | JSON functions can read JSON from strings or use SQL scalars by | ||
| 7438 | converting them to JSON scalars. Such conversion takes time and on | ||
| 7439 | repetitive calls result is significant performance penalty. | ||
| 7440 | |||
| 7441 | Check if such data can be cached: | ||
| 7442 | 1) this item is constant | ||
| 7443 | 2) this item is an arg to a function | ||
| 7444 | 3) it's a source of JSON data | ||
| 7445 | 4) this item's type isn't JSON so conversion will be required | ||
| 7446 | 5) it's not cached already | ||
| 7447 | |||
| 7448 | Difference with the block above is that this one caches any const item, | ||
| 7449 | because the goal here is to avoid conversion, rather than re-evaluation. | ||
| 7450 | */ | ||
| 7451 | 10834050 | else if (const_for_execution() && // 1 | |
| 7452 |
5/6✓ Branch 0 taken 2583078 times.
✓ Branch 1 taken 8250982 times.
✓ Branch 2 taken 2583079 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2580575 times.
✓ Branch 5 taken 8253488 times.
|
13417142 | carg->stack.elements > 0 && |
| 7453 |
2/2✓ Branch 0 taken 2580577 times.
✓ Branch 1 taken 2505 times.
|
2583079 | carg->stack.head()->type() == FUNC_ITEM) // 2 |
| 7454 | { | ||
| 7455 | 2580575 | Item_func *head = down_cast<Item_func *>(carg->stack.head()); | |
| 7456 | enum_const_item_cache what_cache; | ||
| 7457 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 599 times.
|
2581211 | if ((what_cache = head->can_cache_json_arg(this)) && // 3 |
| 7458 |
4/4✓ Branch 0 taken 633 times.
✓ Branch 1 taken 2579946 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 2580545 times.
|
2581212 | data_type() != MYSQL_TYPE_JSON && // 4 |
| 7459 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | item->type() != CACHE_ITEM) // 5 |
| 7460 | { | ||
| 7461 | 34 | carg->cache_item = this; | |
| 7462 | 34 | carg->cache_arg = what_cache; | |
| 7463 | } | ||
| 7464 | } | ||
| 7465 | // Push only if we're going down the tree, so transformer will pop the item | ||
| 7466 | 10979653 | carg->stack.push_front(item); | |
| 7467 | /* | ||
| 7468 | If this item will be cached, no need to explore items further down | ||
| 7469 | in the tree, but the transformer must be called, so return 'true'. | ||
| 7470 | If this item will not be cached, items further down in the tree | ||
| 7471 | must be explored, so return 'true'. | ||
| 7472 | */ | ||
| 7473 | 10979645 | return true; | |
| 7474 | } | ||
| 7475 | /* | ||
| 7476 | An item above in the tree is to be cached, so need to cache the present | ||
| 7477 | item, and no need to go down the tree. | ||
| 7478 | */ | ||
| 7479 | 13887 | return false; | |
| 7480 | } | ||
| 7481 | |||
| 7482 | 80257 | bool Item::can_be_substituted_for_gc(bool array) const { | |
| 7483 |
3/3✓ Branch 0 taken 27071 times.
✓ Branch 1 taken 30287 times.
✓ Branch 2 taken 22899 times.
|
80257 | switch (real_item()->type()) { |
| 7484 | 27071 | case FUNC_ITEM: | |
| 7485 | case COND_ITEM: | ||
| 7486 | 27071 | return true; | |
| 7487 | 30287 | case FIELD_ITEM: | |
| 7488 | // Fields can be substituted with a generated column for a multi-valued | ||
| 7489 | // index defined on the field. Otherwise, for non-arrays, we don't | ||
| 7490 | // substitute fields with generated columns, since functional indexes | ||
| 7491 | // cannot be defined on a plain column, only on expressions. | ||
| 7492 | 30287 | return array; | |
| 7493 | 22899 | default: | |
| 7494 | 22899 | return false; | |
| 7495 | } | ||
| 7496 | } | ||
| 7497 | |||
| 7498 | /** | ||
| 7499 | Set the maximum number of characters required by any of the items in args. | ||
| 7500 | */ | ||
| 7501 | 6752507 | void Item::aggregate_char_length(Item **args, uint nitems) { | |
| 7502 | 6752507 | uint32 char_length = 0; | |
| 7503 | /* | ||
| 7504 | To account for character sets with different number of bytes per character, | ||
| 7505 | set char_length equal to max_length if the aggregated character set is | ||
| 7506 | binary to prevent truncation of data as some characters require more than | ||
| 7507 | one byte. | ||
| 7508 | */ | ||
| 7509 | 6752507 | bool bin_charset = collation.collation == &my_charset_bin; | |
| 7510 |
2/2✓ Branch 0 taken 15434968 times.
✓ Branch 1 taken 6752507 times.
|
22187475 | for (uint i = 0; i < nitems; i++) |
| 7511 |
2/2✓ Branch 0 taken 1266 times.
✓ Branch 1 taken 15433702 times.
|
30868670 | char_length = max(char_length, bin_charset ? args[i]->max_length |
| 7512 |
1/2✓ Branch 0 taken 15433702 times.
✗ Branch 1 not taken.
|
15433702 | : args[i]->max_char_length()); |
| 7513 |
2/2✓ Branch 0 taken 6528846 times.
✓ Branch 1 taken 223661 times.
|
6752507 | if (char_length * collation.collation->mbmaxlen > max_length) |
| 7514 | 6528846 | fix_char_length(char_length); | |
| 7515 | 6752507 | } | |
| 7516 | |||
| 7517 | /** | ||
| 7518 | Set max_length and decimals of function if function is floating point and | ||
| 7519 | result length/precision depends on argument ones. | ||
| 7520 | |||
| 7521 | @param item Argument array. | ||
| 7522 | @param nitems Number of arguments in the array. | ||
| 7523 | */ | ||
| 7524 | 195764 | void Item::aggregate_float_properties(Item **item, uint nitems) { | |
| 7525 |
2/4✓ Branch 0 taken 195764 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 195764 times.
|
195764 | assert(result_type() == REAL_RESULT); |
| 7526 | 195764 | uint32 length = 0; | |
| 7527 | 195764 | uint8 decimals_cnt = 0; | |
| 7528 | 195764 | uint32 maxl = 0; | |
| 7529 |
2/2✓ Branch 0 taken 391440 times.
✓ Branch 1 taken 195764 times.
|
587204 | for (uint i = 0; i < nitems; i++) { |
| 7530 |
2/2✓ Branch 0 taken 238905 times.
✓ Branch 1 taken 152535 times.
|
391440 | if (decimals_cnt != DECIMAL_NOT_SPECIFIED) { |
| 7531 | 238905 | decimals_cnt = max(decimals_cnt, item[i]->decimals); | |
| 7532 | 238905 | length = max(length, (item[i]->max_length - item[i]->decimals)); | |
| 7533 | } | ||
| 7534 | 391440 | maxl = max(maxl, item[i]->max_length); | |
| 7535 | } | ||
| 7536 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 195597 times.
|
195764 | if (decimals_cnt != DECIMAL_NOT_SPECIFIED) { |
| 7537 | 167 | maxl = length; | |
| 7538 | 167 | length += decimals_cnt; | |
| 7539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
|
167 | if (length < maxl) // If previous operation gave overflow |
| 7540 | ✗ | maxl = UINT_MAX32; | |
| 7541 | else | ||
| 7542 | 167 | maxl = length; | |
| 7543 | } | ||
| 7544 | |||
| 7545 | 195764 | this->max_length = maxl; | |
| 7546 | 195764 | this->decimals = decimals_cnt; | |
| 7547 | 195764 | } | |
| 7548 | |||
| 7549 | /** | ||
| 7550 | Set precision and decimals of function when this depends on arguments' | ||
| 7551 | values for these quantities. | ||
| 7552 | |||
| 7553 | @param item Argument array. | ||
| 7554 | @param nitems Number of arguments in the array. | ||
| 7555 | */ | ||
| 7556 | 2032932 | void Item::aggregate_decimal_properties(Item **item, uint nitems) { | |
| 7557 |
2/4✓ Branch 0 taken 2032932 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2032932 times.
|
2032932 | assert(result_type() == DECIMAL_RESULT); |
| 7558 | 2032932 | int max_int_part = 0; | |
| 7559 | 2032932 | uint8 decimal_cnt = 0; | |
| 7560 |
2/2✓ Branch 0 taken 4219671 times.
✓ Branch 1 taken 2032932 times.
|
6252603 | for (uint i = 0; i < nitems; i++) { |
| 7561 | 4219671 | decimal_cnt = max(decimal_cnt, item[i]->decimals); | |
| 7562 |
1/2✓ Branch 0 taken 4219671 times.
✗ Branch 1 not taken.
|
4219671 | max_int_part = max(max_int_part, item[i]->decimal_int_part()); |
| 7563 | } | ||
| 7564 | 2032932 | int precision = min(max_int_part + decimal_cnt, DECIMAL_MAX_PRECISION); | |
| 7565 |
1/2✓ Branch 0 taken 2032932 times.
✗ Branch 1 not taken.
|
2032932 | set_data_type_decimal(precision, decimal_cnt); |
| 7566 | 2032932 | } | |
| 7567 | |||
| 7568 | /** | ||
| 7569 | Set fractional seconds precision for temporal functions. | ||
| 7570 | |||
| 7571 | @param item Argument array | ||
| 7572 | @param nitems Number of arguments in the array. | ||
| 7573 | */ | ||
| 7574 | 182859 | void Item::aggregate_temporal_properties(Item **item, uint nitems) { | |
| 7575 |
2/4✓ Branch 0 taken 182859 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 182859 times.
|
182859 | assert(result_type() == STRING_RESULT); |
| 7576 | 182859 | uint8 decimal_cnt = 0; | |
| 7577 | |||
| 7578 |
5/7✓ Branch 0 taken 182609 times.
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 93 times.
✓ Branch 4 taken 80 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
182859 | switch (data_type()) { |
| 7579 | 182609 | case MYSQL_TYPE_DATETIME: | |
| 7580 |
2/2✓ Branch 0 taken 365211 times.
✓ Branch 1 taken 182609 times.
|
547820 | for (uint i = 0; i < nitems; i++) |
| 7581 |
1/2✓ Branch 0 taken 365211 times.
✗ Branch 1 not taken.
|
365211 | decimal_cnt = max(decimal_cnt, uint8(item[i]->datetime_precision())); |
| 7582 | 182609 | decimal_cnt = min(decimal_cnt, uint8(DATETIME_MAX_DECIMALS)); | |
| 7583 | 182609 | set_data_type_datetime(decimal_cnt); | |
| 7584 | 182609 | break; | |
| 7585 | |||
| 7586 | 75 | case MYSQL_TYPE_TIMESTAMP: | |
| 7587 |
2/2✓ Branch 0 taken 149 times.
✓ Branch 1 taken 75 times.
|
224 | for (uint i = 0; i < nitems; i++) |
| 7588 |
1/2✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
|
149 | decimal_cnt = max(decimal_cnt, uint8(item[i]->datetime_precision())); |
| 7589 | 75 | decimal_cnt = min(decimal_cnt, uint8(DATETIME_MAX_DECIMALS)); | |
| 7590 | 75 | set_data_type_timestamp(decimal_cnt); | |
| 7591 | 75 | break; | |
| 7592 | |||
| 7593 | ✗ | case MYSQL_TYPE_NEWDATE: | |
| 7594 | ✗ | assert(false); | |
| 7595 | set_data_type_date(); | ||
| 7596 | set_data_type(MYSQL_TYPE_NEWDATE); | ||
| 7597 | break; | ||
| 7598 | |||
| 7599 | 93 | case MYSQL_TYPE_DATE: | |
| 7600 | 93 | set_data_type_date(); | |
| 7601 | 93 | break; | |
| 7602 | |||
| 7603 | 80 | case MYSQL_TYPE_TIME: | |
| 7604 |
2/2✓ Branch 0 taken 158 times.
✓ Branch 1 taken 80 times.
|
238 | for (uint i = 0; i < nitems; i++) |
| 7605 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | decimal_cnt = max(decimal_cnt, uint8(item[i]->time_precision())); |
| 7606 | 80 | decimal_cnt = min(decimal_cnt, uint8(DATETIME_MAX_DECIMALS)); | |
| 7607 | 80 | set_data_type_time(decimal_cnt); | |
| 7608 | 80 | break; | |
| 7609 | |||
| 7610 | 2 | case MYSQL_TYPE_YEAR: | |
| 7611 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | set_data_type_year(); |
| 7612 | 2 | break; | |
| 7613 | |||
| 7614 | ✗ | default: | |
| 7615 | ✗ | assert(false); /* purecov: inspected */ | |
| 7616 | } | ||
| 7617 | 182859 | } | |
| 7618 | |||
| 7619 | /** | ||
| 7620 | Aggregate string properties (character set, collation and maximum length) for | ||
| 7621 | string function. | ||
| 7622 | |||
| 7623 | @param name Name of function | ||
| 7624 | @param items Argument array. | ||
| 7625 | @param nitems Number of arguments. | ||
| 7626 | |||
| 7627 | @retval False on success, true on error. | ||
| 7628 | */ | ||
| 7629 | 4859516 | bool Item::aggregate_string_properties(const char *name, Item **items, | |
| 7630 | uint nitems) { | ||
| 7631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4859516 times.
|
4859516 | assert(result_type() == STRING_RESULT); |
| 7632 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4859505 times.
|
4859516 | if (agg_item_charsets_for_string_result(collation, name, items, nitems, 1)) |
| 7633 | 11 | return true; | |
| 7634 |
2/2✓ Branch 0 taken 182859 times.
✓ Branch 1 taken 4676646 times.
|
4859505 | if (is_temporal_type(data_type())) { |
| 7635 | /* | ||
| 7636 | aggregate_temporal_properties() will set collation to numeric, causing | ||
| 7637 | the character set to be explicitly set to latin1, which may not match the | ||
| 7638 | aggregated character set. The collation must therefore be restored after | ||
| 7639 | the temporal properties have been computed. | ||
| 7640 | */ | ||
| 7641 | 182859 | auto aggregated_collation = collation; | |
| 7642 |
1/2✓ Branch 0 taken 182859 times.
✗ Branch 1 not taken.
|
182859 | aggregate_temporal_properties(items, nitems); |
| 7643 | 182859 | collation.set(aggregated_collation); | |
| 7644 | /* | ||
| 7645 | Set max_length again as the aggregated character set may have different | ||
| 7646 | number of bytes per character than latin1. | ||
| 7647 | */ | ||
| 7648 | 182859 | fix_char_length(max_length); | |
| 7649 | } else | ||
| 7650 | 4676646 | decimals = min(decimals, uint8(DECIMAL_NOT_SPECIFIED)); | |
| 7651 | 4859505 | aggregate_char_length(items, nitems); | |
| 7652 | |||
| 7653 | /* | ||
| 7654 | If the resulting data type is a fixed length character or binary string | ||
| 7655 | and the result maximum length in characters is longer than the MySQL | ||
| 7656 | maximum CHAR/BINARY size, convert to a variable-sized type. | ||
| 7657 | */ | ||
| 7658 |
3/4✓ Branch 0 taken 304 times.
✓ Branch 1 taken 4859201 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4859505 times.
|
4859809 | if (data_type() == MYSQL_TYPE_STRING && |
| 7659 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 304 times.
|
304 | max_char_length() > MAX_FIELD_CHARLENGTH) |
| 7660 | ✗ | set_data_type(MYSQL_TYPE_VARCHAR); | |
| 7661 | |||
| 7662 | 4859505 | return false; | |
| 7663 | } | ||
| 7664 | |||
| 7665 | /** | ||
| 7666 | This function is used to resolve type for numeric result type of CASE, | ||
| 7667 | COALESCE, IF and LEAD/LAG. COALESCE is a CASE abbreviation according to the | ||
| 7668 | standard. | ||
| 7669 | |||
| 7670 | @param result_type The desired result type | ||
| 7671 | @param item The arguments of func | ||
| 7672 | @param nitems The number of arguments | ||
| 7673 | */ | ||
| 7674 | 3926137 | void Item::aggregate_num_type(Item_result result_type, Item **item, | |
| 7675 | uint nitems) { | ||
| 7676 | 3926137 | collation.set_numeric(); | |
| 7677 |
3/4✓ Branch 0 taken 2032932 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 1893002 times.
✗ Branch 3 not taken.
|
3926137 | switch (result_type) { |
| 7678 | 2032932 | case DECIMAL_RESULT: | |
| 7679 | 2032932 | aggregate_decimal_properties(item, nitems); | |
| 7680 | 2032932 | break; | |
| 7681 | 203 | case REAL_RESULT: | |
| 7682 | 203 | aggregate_float_properties(item, nitems); | |
| 7683 | 203 | break; | |
| 7684 | 1893002 | case INT_RESULT: | |
| 7685 | case STRING_RESULT: | ||
| 7686 | 1893002 | aggregate_char_length(item, nitems); | |
| 7687 | 1893002 | decimals = 0; | |
| 7688 | 1893002 | break; | |
| 7689 | ✗ | case ROW_RESULT: | |
| 7690 | default: | ||
| 7691 | ✗ | assert(0); | |
| 7692 | } | ||
| 7693 | 3926137 | } | |
| 7694 | |||
| 7695 | /** | ||
| 7696 | Cache item if needed. | ||
| 7697 | |||
| 7698 | @param arg Descriptor of what and how to cache @see cache_const_expr_arg | ||
| 7699 | |||
| 7700 | @return cache if cache needed. | ||
| 7701 | @return this otherwise. | ||
| 7702 | */ | ||
| 7703 | |||
| 7704 | 10979614 | Item *Item::cache_const_expr_transformer(uchar *arg) { | |
| 7705 | 10979614 | cache_const_expr_arg *carg = (cache_const_expr_arg *)arg; | |
| 7706 | 10979614 | carg->stack.pop(); | |
| 7707 |
2/2✓ Branch 0 taken 145620 times.
✓ Branch 1 taken 10834023 times.
|
10979643 | if (carg->cache_item) // Item is to be cached, note that it is used as a flag |
| 7708 | { | ||
| 7709 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 145620 times.
|
145620 | assert(carg->cache_item == this); |
| 7710 | Item_cache *cache; | ||
| 7711 | /* | ||
| 7712 | Flag applies to present item, must reset it so it does not affect | ||
| 7713 | the parent item. | ||
| 7714 | */ | ||
| 7715 | 145620 | carg->cache_item = nullptr; | |
| 7716 | // Cache arg of a JSON function to avoid repetitive conversion | ||
| 7717 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 145586 times.
|
145620 | if (carg->cache_arg != CACHE_NONE) { |
| 7718 | 34 | Item *itm = this; | |
| 7719 | 34 | Item_func *caller = down_cast<Item_func *>(carg->stack.head()); | |
| 7720 | 34 | String buf; | |
| 7721 | 34 | Json_wrapper wr; | |
| 7722 | 34 | enum_const_item_cache what_cache = carg->cache_arg; | |
| 7723 | |||
| 7724 | 34 | carg->cache_arg = CACHE_NONE; | |
| 7725 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 13 times.
|
34 | if (what_cache == CACHE_JSON_VALUE) { |
| 7726 | // Cache parse result of JSON string | ||
| 7727 |
6/8✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 20 times.
|
41 | if (get_json_wrapper(&itm, 0, &buf, caller->func_name(), &wr) || |
| 7728 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | null_value) { |
| 7729 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return current_thd->is_error() ? nullptr : this; |
| 7730 | } | ||
| 7731 | } else { | ||
| 7732 | // Cache SQL scalar converted to JSON | ||
| 7733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(what_cache == CACHE_JSON_ATOM); |
| 7734 | 13 | String conv_buf; | |
| 7735 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
13 | if (get_json_atom_wrapper(&itm, 0, caller->func_name(), &buf, &conv_buf, |
| 7736 |
3/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11 times.
|
26 | &wr, nullptr, true) || |
| 7737 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
|
13 | null_value) { |
| 7738 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | return current_thd->is_error() ? nullptr : this; |
| 7739 | } | ||
| 7740 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
|
13 | } |
| 7741 | // Should've been checked at get_*_wrapper() | ||
| 7742 |
2/4✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31 times.
|
31 | assert(wr.type() != enum_json_type::J_ERROR); |
| 7743 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
62 | Item_cache_json *jcache = new Item_cache_json(); |
| 7744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | if (!jcache) return nullptr; |
| 7745 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | jcache->setup(this); |
| 7746 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | jcache->store_value(this, &wr); |
| 7747 | 31 | cache = jcache; | |
| 7748 |
4/4✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 3 times.
|
37 | } else { |
| 7749 | 145586 | cache = Item_cache::get_cache(this); | |
| 7750 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 145586 times.
|
145586 | if (!cache) return nullptr; |
| 7751 | 145586 | cache->setup(this); | |
| 7752 | 145586 | cache->store(this); | |
| 7753 | } | ||
| 7754 | /* | ||
| 7755 | This item is cached - for subqueries this effectively means that they | ||
| 7756 | are optimized away. | ||
| 7757 | */ | ||
| 7758 | 145617 | mark_subqueries_optimized_away(); | |
| 7759 | 145617 | return cache; | |
| 7760 | } | ||
| 7761 | 10834023 | return this; | |
| 7762 | } | ||
| 7763 | |||
| 7764 | 445445542 | bool Item_field::send(Protocol *protocol, String *) { | |
| 7765 | 445445542 | return protocol->store_field(field); | |
| 7766 | } | ||
| 7767 | |||
| 7768 | /** | ||
| 7769 | Add the field to the select list and substitute it for the reference to | ||
| 7770 | the field. | ||
| 7771 | |||
| 7772 | @details | ||
| 7773 | If the field doesn't belong to the table being inserted into then it is | ||
| 7774 | added to the select list, pointer to it is stored in the ref_item_array | ||
| 7775 | of the select and the field itself is substituted for the Item_ref object. | ||
| 7776 | This is done in order to get correct values from update fields that | ||
| 7777 | belongs to the SELECT part in the INSERT .. SELECT .. ON DUPLICATE KEY | ||
| 7778 | UPDATE statement. | ||
| 7779 | |||
| 7780 | @retval nullptr if an error occurred | ||
| 7781 | @retval ref if all conditions are met | ||
| 7782 | @retval this field otherwise | ||
| 7783 | */ | ||
| 7784 | |||
| 7785 | 228 | Item *Item_field::update_value_transformer(uchar *select_arg) { | |
| 7786 | 228 | Query_block *select = pointer_cast<Query_block *>(select_arg); | |
| 7787 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
|
228 | assert(fixed); |
| 7788 | |||
| 7789 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
|
228 | assert((table_ref == select->context.table_list) == |
| 7790 | (field->table == select->context.table_list->table)); | ||
| 7791 |
4/4✓ Branch 0 taken 115 times.
✓ Branch 1 taken 113 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 116 times.
|
343 | if (field->table != select->context.table_list->table && |
| 7792 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 3 times.
|
115 | type() != Item::TRIGGER_FIELD_ITEM) { |
| 7793 | 112 | Item **tmp = select->add_hidden_item(this); | |
| 7794 |
2/4✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
|
112 | return new Item_ref(&select->context, tmp, db_name, table_name, field_name); |
| 7795 | } | ||
| 7796 | 116 | return this; | |
| 7797 | } | ||
| 7798 | |||
| 7799 | 5193429 | void Item_field::print(const THD *thd, String *str, | |
| 7800 | enum_query_type query_type) const { | ||
| 7801 |
6/6✓ Branch 0 taken 5176326 times.
✓ Branch 1 taken 17103 times.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 5176128 times.
✓ Branch 4 taken 198 times.
✓ Branch 5 taken 5193231 times.
|
5193429 | if (field && field->is_field_for_functional_index()) { |
| 7802 | 198 | field->gcol_info->expr_item->print(thd, str, query_type); | |
| 7803 | 198 | return; | |
| 7804 | } | ||
| 7805 | |||
| 7806 |
6/6✓ Branch 0 taken 5176129 times.
✓ Branch 1 taken 17102 times.
✓ Branch 2 taken 5175521 times.
✓ Branch 3 taken 608 times.
✓ Branch 4 taken 1980 times.
✓ Branch 5 taken 5173541 times.
|
5193231 | if (field && field->table && field->table->const_table && |
| 7807 |
2/2✓ Branch 0 taken 1921 times.
✓ Branch 1 taken 59 times.
|
1980 | !(query_type & QT_NO_DATA_EXPANSION)) { |
| 7808 | char buff[MAX_FIELD_WIDTH]; | ||
| 7809 | 1921 | String tmp(buff, sizeof(buff), str->charset()); | |
| 7810 |
1/2✓ Branch 0 taken 1921 times.
✗ Branch 1 not taken.
|
1921 | field->val_str(&tmp); |
| 7811 |
3/4✓ Branch 0 taken 1921 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 881 times.
✓ Branch 3 taken 1040 times.
|
1921 | if (field->is_null()) |
| 7812 |
1/2✓ Branch 0 taken 881 times.
✗ Branch 1 not taken.
|
881 | str->append("NULL"); |
| 7813 | else { | ||
| 7814 |
1/2✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
|
1040 | str->append('\''); |
| 7815 |
1/2✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
|
1040 | str->append(tmp); |
| 7816 |
1/2✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
|
1040 | str->append('\''); |
| 7817 | } | ||
| 7818 | 1921 | return; | |
| 7819 | 1921 | } | |
| 7820 | 5191310 | Item_ident::print(thd, str, query_type); | |
| 7821 | } | ||
| 7822 | |||
| 7823 | /** | ||
| 7824 | Calculate condition filtering effect for "WHERE field", which | ||
| 7825 | implicitly means "WHERE field <> 0". The filtering effect is | ||
| 7826 | therefore identical to that of Item_func_ne. | ||
| 7827 | */ | ||
| 7828 | ✗ | float Item_field::get_filtering_effect(THD *, table_map filter_for_table, | |
| 7829 | table_map, | ||
| 7830 | const MY_BITMAP *fields_to_ignore, | ||
| 7831 | double rows_in_table) { | ||
| 7832 | ✗ | if (used_tables() != filter_for_table || | |
| 7833 | ✗ | bitmap_is_set(fields_to_ignore, field->field_index())) | |
| 7834 | ✗ | return COND_FILTER_ALLPASS; | |
| 7835 | |||
| 7836 | ✗ | return 1.0f - get_cond_filter_default_probability(rows_in_table, | |
| 7837 | ✗ | COND_FILTER_EQUALITY); | |
| 7838 | } | ||
| 7839 | |||
| 7840 | 178998627 | float Item_field::get_cond_filter_default_probability( | |
| 7841 | double max_distinct_values, float default_filter) const { | ||
| 7842 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178998627 times.
|
178998627 | assert(max_distinct_values >= 1.0); |
| 7843 | |||
| 7844 | // Some field types have a limited number of possible values | ||
| 7845 |
3/3✓ Branch 0 taken 788138 times.
✓ Branch 1 taken 2870 times.
✓ Branch 2 taken 178207662 times.
|
178998627 | switch (field->real_type()) { |
| 7846 | 788138 | case MYSQL_TYPE_ENUM: { | |
| 7847 | // ENUM can only have the values defined in the typelib | ||
| 7848 | 788138 | const uint enum_values = static_cast<Field_enum *>(field)->typelib->count; | |
| 7849 | 788138 | max_distinct_values = | |
| 7850 | 788138 | min(static_cast<double>(enum_values), max_distinct_values); | |
| 7851 | 788138 | break; | |
| 7852 | } | ||
| 7853 | 2870 | case MYSQL_TYPE_BIT: { | |
| 7854 | // BIT(N) can have no more than 2^N distinct values | ||
| 7855 | 2870 | const uint bits = static_cast<Field_bit *>(field)->field_length; | |
| 7856 | 2870 | const double combos = pow(2.0, (int)bits); | |
| 7857 | 2870 | max_distinct_values = min(combos, max_distinct_values); | |
| 7858 | 2880 | break; | |
| 7859 | } | ||
| 7860 | 178207662 | default: | |
| 7861 | 178207662 | break; | |
| 7862 | } | ||
| 7863 | 178998680 | return max(static_cast<float>(1 / max_distinct_values), default_filter); | |
| 7864 | } | ||
| 7865 | |||
| 7866 | 4610691 | Item_ref::Item_ref(Name_resolution_context *context_arg, Item **item, | |
| 7867 | const char *db_name_arg, const char *table_name_arg, | ||
| 7868 | 4610691 | const char *field_name_arg, bool alias_of_expr_arg) | |
| 7869 | : Item_ident(context_arg, db_name_arg, table_name_arg, field_name_arg), | ||
| 7870 | 4610691 | ref(item) { | |
| 7871 | 4610691 | m_alias_of_expr = alias_of_expr_arg; | |
| 7872 | /* | ||
| 7873 | This constructor used to create some internals references over fixed items | ||
| 7874 | */ | ||
| 7875 |
6/8✓ Branch 0 taken 4610570 times.
✓ Branch 1 taken 121 times.
✓ Branch 2 taken 4610487 times.
✓ Branch 3 taken 83 times.
✓ Branch 4 taken 4610487 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4610487 times.
✗ Branch 7 not taken.
|
4610691 | if (ref && *ref && (*ref)->fixed) set_properties(); |
| 7876 | 4610691 | } | |
| 7877 | |||
| 7878 | 8228 | Item_ref::Item_ref(Name_resolution_context *context_arg, Item **item, | |
| 7879 | 8228 | const char *field_name_arg) | |
| 7880 | 8228 | : Item_ident(context_arg, "", "", field_name_arg), ref(item) { | |
| 7881 |
2/4✓ Branch 0 taken 8228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8228 times.
✗ Branch 3 not taken.
|
8228 | assert(ref && *ref); |
| 7882 |
2/4✓ Branch 0 taken 8228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8228 times.
✗ Branch 3 not taken.
|
8228 | if ((*ref)->fixed) set_properties(); |
| 7883 | 8228 | } | |
| 7884 | |||
| 7885 | /** | ||
| 7886 | Resolve the name of a reference to a column reference. | ||
| 7887 | |||
| 7888 | The method resolves the column reference represented by 'this' as a column | ||
| 7889 | present in one of: GROUP BY clause, SELECT clause, outer queries. It is | ||
| 7890 | used typically for columns in the HAVING clause which are not under | ||
| 7891 | aggregate functions. | ||
| 7892 | |||
| 7893 | POSTCONDITION @n | ||
| 7894 | Item_ref::ref is 0 or points to a valid item. | ||
| 7895 | |||
| 7896 | @note | ||
| 7897 | The name resolution algorithm used is (where [T_j] is an optional table | ||
| 7898 | name that qualifies the column name): | ||
| 7899 | |||
| 7900 | @code | ||
| 7901 | resolve_extended([T_j].col_ref_i) | ||
| 7902 | { | ||
| 7903 | Search for a column or derived column named col_ref_i [in table T_j] | ||
| 7904 | in the SELECT and GROUP clauses of Q. | ||
| 7905 | |||
| 7906 | if such a column is NOT found AND // Lookup in outer queries. | ||
| 7907 | there are outer queries | ||
| 7908 | { | ||
| 7909 | for each outer query Q_k beginning from the inner-most one | ||
| 7910 | { | ||
| 7911 | Search for a column or derived column named col_ref_i | ||
| 7912 | [in table T_j] in the SELECT and GROUP clauses of Q_k. | ||
| 7913 | |||
| 7914 | if such a column is not found AND | ||
| 7915 | - Q_k is not a group query AND | ||
| 7916 | - Q_k is not inside an aggregate function | ||
| 7917 | OR | ||
| 7918 | - Q_(k-1) is not in a HAVING or SELECT clause of Q_k | ||
| 7919 | { | ||
| 7920 | search for a column or derived column named col_ref_i | ||
| 7921 | [in table T_j] in the FROM clause of Q_k; | ||
| 7922 | } | ||
| 7923 | } | ||
| 7924 | } | ||
| 7925 | } | ||
| 7926 | @endcode | ||
| 7927 | @n | ||
| 7928 | This procedure treats GROUP BY and SELECT clauses as one namespace for | ||
| 7929 | column references in HAVING. Notice that compared to | ||
| 7930 | Item_field::fix_fields, here we first search the SELECT and GROUP BY | ||
| 7931 | clauses, and then we search the FROM clause. | ||
| 7932 | |||
| 7933 | @param[in] thd current thread | ||
| 7934 | @param[in,out] reference view column if this item was resolved to a | ||
| 7935 | view column | ||
| 7936 | |||
| 7937 | @todo | ||
| 7938 | Here we could first find the field anyway, and then test this | ||
| 7939 | condition, so that we can give a better error message - | ||
| 7940 | ER_WRONG_FIELD_WITH_GROUP, instead of the less informative | ||
| 7941 | ER_BAD_FIELD_ERROR which we produce now. | ||
| 7942 | |||
| 7943 | @retval | ||
| 7944 | true if error | ||
| 7945 | @retval | ||
| 7946 | false on success | ||
| 7947 | */ | ||
| 7948 | |||
| 7949 | 1290 | bool Item_ref::fix_fields(THD *thd, Item **reference) { | |
| 7950 |
1/2✓ Branch 0 taken 1290 times.
✗ Branch 1 not taken.
|
1290 | DBUG_TRACE; |
| 7951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1290 times.
|
1290 | assert(fixed == 0); |
| 7952 | |||
| 7953 | Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler( | ||
| 7954 |
1/2✓ Branch 0 taken 1290 times.
✗ Branch 1 not taken.
|
1290 | thd, context->view_error_handler, context->view_error_handler_arg); |
| 7955 | |||
| 7956 |
3/4✓ Branch 0 taken 204 times.
✓ Branch 1 taken 1086 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 204 times.
|
1290 | if (!ref || ref == not_found_item) { |
| 7957 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1086 times.
|
1086 | assert(context->query_block == thd->lex->current_query_block()); |
| 7958 | 1086 | if (!(ref = | |
| 7959 |
3/4✓ Branch 0 taken 1086 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1083 times.
|
1086 | resolve_ref_in_select_and_group(thd, this, context->query_block))) |
| 7960 | 3 | goto error; /* Some error occurred (e.g. ambiguous names). */ | |
| 7961 | |||
| 7962 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 995 times.
|
1083 | if (ref == not_found_item) /* This reference was not resolved. */ |
| 7963 | { | ||
| 7964 | 88 | Name_resolution_context *last_checked_context = context; | |
| 7965 | 88 | Name_resolution_context *outer_context = context->outer_context; | |
| 7966 | Field *from_field; | ||
| 7967 | 88 | ref = nullptr; | |
| 7968 | |||
| 7969 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 79 times.
|
88 | if (!outer_context) { |
| 7970 | /* The current reference cannot be resolved in this query. */ | ||
| 7971 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | my_error(ER_BAD_FIELD_ERROR, MYF(0), this->full_name(), |
| 7972 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | current_thd->where); |
| 7973 | 9 | goto error; | |
| 7974 | } | ||
| 7975 | |||
| 7976 | /* | ||
| 7977 | If there is an outer context (select), try to | ||
| 7978 | resolve this reference in the outer select(s). | ||
| 7979 | |||
| 7980 | We treat each subselect as a separate namespace, so that different | ||
| 7981 | subselects may contain columns with the same names. The subselects are | ||
| 7982 | searched starting from the innermost. | ||
| 7983 | */ | ||
| 7984 | 79 | from_field = not_found_field; | |
| 7985 | |||
| 7986 | 79 | Query_block *cur_query_block = context->query_block; | |
| 7987 | |||
| 7988 | do { | ||
| 7989 | 91 | Query_block *select = outer_context->query_block; | |
| 7990 | 91 | last_checked_context = outer_context; | |
| 7991 | 91 | Query_expression *cur_query_expression = nullptr; | |
| 7992 | 91 | enum_parsing_context place = CTX_NONE; | |
| 7993 | |||
| 7994 | // See comments and similar loop in Item_field::fix_outer_field() | ||
| 7995 | while (true) { | ||
| 7996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
|
127 | if (!cur_query_block) goto loop; |
| 7997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
|
127 | assert(cur_query_block != select); |
| 7998 | 127 | cur_query_expression = cur_query_block->master_query_expression(); | |
| 7999 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 36 times.
|
127 | if (cur_query_expression->outer_query_block() == select) break; |
| 8000 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | cur_query_expression->accumulate_used_tables(OUTER_REF_TABLE_BIT); |
| 8001 | 36 | cur_query_block = cur_query_expression->outer_query_block(); | |
| 8002 | } | ||
| 8003 | |||
| 8004 |
1/2✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
|
91 | place = cur_query_expression->place(); |
| 8005 | |||
| 8006 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
91 | if (place == CTX_DERIVED && select->end_lateral_table == nullptr) |
| 8007 | ✗ | goto loop; | |
| 8008 | |||
| 8009 | /* Search in the SELECT and GROUP lists of the outer select. */ | ||
| 8010 |
4/4✓ Branch 0 taken 61 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 30 times.
|
152 | if (select_alias_referencable(place) && |
| 8011 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
61 | outer_context->resolve_in_select_list) { |
| 8012 |
2/4✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 61 times.
|
61 | if (!(ref = resolve_ref_in_select_and_group(thd, this, select))) |
| 8013 | ✗ | goto error; /* Some error occurred (e.g. ambiguous names). */ | |
| 8014 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 25 times.
|
61 | if (ref != not_found_item) { |
| 8015 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | assert((*ref)->fixed); |
| 8016 |
2/4✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
36 | cur_query_expression->accumulate_used_tables((*ref)->used_tables()); |
| 8017 | 36 | break; | |
| 8018 | } | ||
| 8019 | /* | ||
| 8020 | Set ref to 0 to ensure that we get an error in case we replaced | ||
| 8021 | this item with another item and still use this item in some | ||
| 8022 | other place of the parse tree. | ||
| 8023 | */ | ||
| 8024 | 25 | ref = nullptr; | |
| 8025 | } | ||
| 8026 | |||
| 8027 | /* | ||
| 8028 | Check table fields only if the subquery is used in a context that | ||
| 8029 | is not the HAVING clause, or in case the HAVING clause can be | ||
| 8030 | implemented as a WHERE clause (i.e. the query block is not grouped | ||
| 8031 | - implicitly or explicitly - and DISTINCT filtering is not present). | ||
| 8032 | TODO: | ||
| 8033 | Implement proper SQL resolving, by looking at fields from columns | ||
| 8034 | only and reject fields in HAVING clause that are not functionally | ||
| 8035 | dependent on grouping columns from this query block. | ||
| 8036 | In order to preserve MySQL semantics, we may need to accept | ||
| 8037 | fields from the SELECT fields, until this feature has been removed. | ||
| 8038 | */ | ||
| 8039 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 3 times.
|
58 | if (place != CTX_HAVING || |
| 8040 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
3 | (!select->with_sum_func && select->group_list.elements == 0 && |
| 8041 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | !select->is_distinct())) { |
| 8042 | /* | ||
| 8043 | In case of view, find_field_in_tables() write pointer to view | ||
| 8044 | field expression to 'reference', i.e. it substitute that | ||
| 8045 | expression instead of this Item_ref | ||
| 8046 | */ | ||
| 8047 |
1/2✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
|
52 | from_field = find_field_in_tables( |
| 8048 | thd, this, outer_context->first_name_resolution_table, | ||
| 8049 | outer_context->last_name_resolution_table, reference, | ||
| 8050 | IGNORE_EXCEPT_NON_UNIQUE, thd->want_privilege, true); | ||
| 8051 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 51 times.
|
52 | if (!from_field) goto error; |
| 8052 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 50 times.
|
51 | if (from_field == view_ref_found) { |
| 8053 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | Item::Type refer_type = (*reference)->type(); |
| 8054 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | cur_query_expression->accumulate_used_tables( |
| 8055 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | (*reference)->used_tables()); |
| 8056 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | assert((*reference)->type() == REF_ITEM); |
| 8057 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | mark_as_dependent( |
| 8058 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | thd, last_checked_context->query_block, context->query_block, |
| 8059 | this, | ||
| 8060 | ✗ | ((refer_type == REF_ITEM || refer_type == FIELD_ITEM) | |
| 8061 | ? (Item_ident *)(*reference) | ||
| 8062 | : nullptr)); | ||
| 8063 | /* | ||
| 8064 | view reference found, we substituted it instead of this | ||
| 8065 | Item, so can quit | ||
| 8066 | */ | ||
| 8067 | 1 | return false; | |
| 8068 | } | ||
| 8069 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 12 times.
|
50 | if (from_field != not_found_field) { |
| 8070 |
2/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | if (cached_table && cached_table->query_block && |
| 8071 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | outer_context->query_block && |
| 8072 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | cached_table->query_block != outer_context->query_block) { |
| 8073 | /* | ||
| 8074 | Due to cache, find_field_in_tables() can return field which | ||
| 8075 | doesn't belong to provided outer_context. In this case we have | ||
| 8076 | to find proper field context in order to fix field correctly. | ||
| 8077 | */ | ||
| 8078 | do { | ||
| 8079 | ✗ | outer_context = outer_context->outer_context; | |
| 8080 | ✗ | select = outer_context->query_block; | |
| 8081 | ✗ | cur_query_expression = last_checked_context->query_block | |
| 8082 | ✗ | ->master_query_expression(); | |
| 8083 | ✗ | last_checked_context = outer_context; | |
| 8084 | ✗ | } while (outer_context && outer_context->query_block && | |
| 8085 | ✗ | cached_table->query_block != outer_context->query_block); | |
| 8086 | ✗ | place = cur_query_expression->place(); | |
| 8087 | } | ||
| 8088 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | cur_query_expression->accumulate_used_tables( |
| 8089 | 38 | from_field->table->pos_in_table_list->map()); | |
| 8090 | 38 | break; | |
| 8091 | } | ||
| 8092 | } | ||
| 8093 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(from_field == not_found_field); |
| 8094 | |||
| 8095 | /* Reference is not found => depend on outer (or just error). */ | ||
| 8096 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | cur_query_expression->accumulate_used_tables(OUTER_REF_TABLE_BIT); |
| 8097 | |||
| 8098 | 15 | loop: | |
| 8099 | 15 | outer_context = outer_context->outer_context; | |
| 8100 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
|
15 | } while (outer_context); |
| 8101 | |||
| 8102 |
2/4✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
|
77 | assert(from_field != nullptr && from_field != view_ref_found); |
| 8103 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 39 times.
|
77 | if (from_field != not_found_field) { |
| 8104 | Item_field *fld; | ||
| 8105 | |||
| 8106 | { | ||
| 8107 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | Prepared_stmt_arena_holder ps_arena_holder(thd); |
| 8108 | 38 | fld = new Item_field( | |
| 8109 |
2/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | thd, context, from_field->table->pos_in_table_list, from_field); |
| 8110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (fld == nullptr) goto error; |
| 8111 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | } |
| 8112 | |||
| 8113 | 38 | *reference = fld; | |
| 8114 | // WL#6570 remove-after-qa | ||
| 8115 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
38 | assert(thd->stmt_arena->is_regular() || !thd->lex->is_exec_started()); |
| 8116 | 38 | mark_as_dependent(thd, last_checked_context->query_block, | |
| 8117 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | context->query_block, this, fld); |
| 8118 | /* | ||
| 8119 | A reference is resolved to a nest level that's outer or the same as | ||
| 8120 | the nest level of the enclosing set function : adjust the value of | ||
| 8121 | max_aggr_level for the function if it's needed. | ||
| 8122 | */ | ||
| 8123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (thd->lex->in_sum_func && |
| 8124 | ✗ | thd->lex->in_sum_func->base_query_block->nest_level >= | |
| 8125 | ✗ | last_checked_context->query_block->nest_level) | |
| 8126 | ✗ | thd->lex->in_sum_func->max_aggr_level = | |
| 8127 | ✗ | max(thd->lex->in_sum_func->max_aggr_level, | |
| 8128 | ✗ | int8(last_checked_context->query_block->nest_level)); | |
| 8129 | 38 | return false; | |
| 8130 | } | ||
| 8131 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 36 times.
|
39 | if (ref == nullptr) { |
| 8132 | /* The item was not a table field and not a reference */ | ||
| 8133 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_BAD_FIELD_ERROR, MYF(0), this->full_name(), |
| 8134 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | current_thd->where); |
| 8135 | 3 | goto error; | |
| 8136 | } | ||
| 8137 | /* Should be checked in resolve_ref_in_select_and_group(). */ | ||
| 8138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | assert((*ref)->fixed); |
| 8139 | 36 | mark_as_dependent(thd, last_checked_context->query_block, | |
| 8140 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | context->query_block, this, this); |
| 8141 | /* | ||
| 8142 | A reference is resolved to a nest level that's outer or the same as | ||
| 8143 | the nest level of the enclosing set function : adjust the value of | ||
| 8144 | max_aggr_level for the function if it's needed. | ||
| 8145 | */ | ||
| 8146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | if (thd->lex->in_sum_func && |
| 8147 | ✗ | thd->lex->in_sum_func->base_query_block->nest_level >= | |
| 8148 | ✗ | last_checked_context->query_block->nest_level) | |
| 8149 | ✗ | thd->lex->in_sum_func->max_aggr_level = | |
| 8150 | ✗ | max(thd->lex->in_sum_func->max_aggr_level, | |
| 8151 | ✗ | int8(last_checked_context->query_block->nest_level)); | |
| 8152 | } | ||
| 8153 | } | ||
| 8154 | |||
| 8155 | // The reference should be fixed at this point. | ||
| 8156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1235 times.
|
1235 | assert((*ref)->fixed); |
| 8157 | |||
| 8158 | /* | ||
| 8159 | Reject invalid references to aggregates. | ||
| 8160 | |||
| 8161 | 1) We only accept references to aggregates in a HAVING clause. | ||
| 8162 | (This restriction is not strictly necessary, but we don't want to | ||
| 8163 | lift it without making sure that such queries are handled | ||
| 8164 | correctly. Lifting the restriction will make bugs such as | ||
| 8165 | bug#13633829 and bug#22588319 (aka bug#80116) affect a larger set | ||
| 8166 | of queries.) | ||
| 8167 | |||
| 8168 | 2) An aggregate cannot be referenced from the GROUP BY clause of | ||
| 8169 | the query block where the aggregation happens, since grouping | ||
| 8170 | happens before aggregation. | ||
| 8171 | */ | ||
| 8172 | 1235 | if (((*ref)->has_aggregation() && | |
| 8173 |
6/6✓ Branch 0 taken 372 times.
✓ Branch 1 taken 863 times.
✓ Branch 2 taken 337 times.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 1191 times.
|
2435 | !thd->lex->current_query_block()->having_fix_field) || // 1 |
| 8174 |
3/4✓ Branch 0 taken 1200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1191 times.
|
1200 | walk(&Item::has_aggregate_ref_in_group_by, // 2 |
| 8175 | enum_walk::SUBQUERY_POSTFIX, nullptr)) { | ||
| 8176 |
2/4✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | my_error(ER_ILLEGAL_REFERENCE, MYF(0), full_name(), |
| 8177 | "reference to group function"); | ||
| 8178 | 44 | goto error; | |
| 8179 | } | ||
| 8180 | |||
| 8181 |
1/2✓ Branch 0 taken 1191 times.
✗ Branch 1 not taken.
|
1191 | set_properties(); |
| 8182 | |||
| 8183 |
2/4✓ Branch 0 taken 1191 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1191 times.
|
1191 | if ((*ref)->check_cols(1)) goto error; |
| 8184 | 1191 | return false; | |
| 8185 | |||
| 8186 | 60 | error: | |
| 8187 | 60 | return true; | |
| 8188 | 1290 | } | |
| 8189 | |||
| 8190 | 4620027 | void Item_ref::set_properties() { | |
| 8191 |
1/2✓ Branch 0 taken 4620027 times.
✗ Branch 1 not taken.
|
4620027 | DBUG_TRACE; |
| 8192 | |||
| 8193 | 4620027 | set_data_type((*ref)->data_type()); | |
| 8194 | 4620027 | max_length = (*ref)->max_length; | |
| 8195 | 4620027 | set_nullable((*ref)->is_nullable()); | |
| 8196 | 4620027 | decimals = (*ref)->decimals; | |
| 8197 | 4620027 | collation.set((*ref)->collation); | |
| 8198 | /* | ||
| 8199 | We have to remember if we refer to a sum function, to ensure that | ||
| 8200 | split_sum_func() doesn't try to change the reference. | ||
| 8201 | */ | ||
| 8202 | 4620027 | set_accum_properties(*ref); | |
| 8203 | 4620026 | unsigned_flag = (*ref)->unsigned_flag; | |
| 8204 | 4620026 | fixed = true; | |
| 8205 |
5/8✓ Branch 0 taken 4620026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2683730 times.
✓ Branch 3 taken 1936296 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2683730 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4620026 times.
|
7303756 | if ((*ref)->type() == FIELD_ITEM && |
| 8206 | 2683730 | ((Item_ident *)(*ref))->is_alias_of_expr()) | |
| 8207 | ✗ | set_alias_of_expr(); | |
| 8208 | 4620026 | } | |
| 8209 | |||
| 8210 | 4592362 | void Item_ref::cleanup() { | |
| 8211 |
1/2✓ Branch 0 taken 4592372 times.
✗ Branch 1 not taken.
|
4592362 | DBUG_TRACE; |
| 8212 | 4592372 | Item_ident::cleanup(); | |
| 8213 | 4592371 | result_field = nullptr; | |
| 8214 | 4592371 | } | |
| 8215 | |||
| 8216 | /** | ||
| 8217 | Transform an Item_ref object with a transformer callback function. | ||
| 8218 | |||
| 8219 | The function first applies the transform function to the item | ||
| 8220 | referenced by this Item_ref object. If this replaces the item with a | ||
| 8221 | new one, this item object is returned as the result of the | ||
| 8222 | transform. Otherwise the transform function is applied to the | ||
| 8223 | Item_ref object itself. | ||
| 8224 | */ | ||
| 8225 | |||
| 8226 | 57 | Item *Item_ref::transform(Item_transformer transformer, uchar *arg) { | |
| 8227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | assert((*ref) != nullptr); |
| 8228 | |||
| 8229 | /* Transform the object we are referencing. */ | ||
| 8230 | 57 | Item *new_item = (*ref)->transform(transformer, arg); | |
| 8231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (new_item == nullptr) return nullptr; |
| 8232 | |||
| 8233 | /* | ||
| 8234 | If the object is transformed into a new object, discard the Item_ref | ||
| 8235 | object and return the new object as result. | ||
| 8236 | */ | ||
| 8237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
|
57 | if (new_item != *ref) return new_item; |
| 8238 | |||
| 8239 | /* Transform the item ref object. */ | ||
| 8240 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | Item *transformed_item = (this->*transformer)(arg); |
| 8241 | // assert(transformed_item == this); | ||
| 8242 | 57 | return transformed_item; | |
| 8243 | } | ||
| 8244 | |||
| 8245 | /** | ||
| 8246 | Compile an Item_ref object with a processor and a transformer | ||
| 8247 | callback function. | ||
| 8248 | |||
| 8249 | First the function applies the analyzer to the Item_ref | ||
| 8250 | object. Second it applies the compile function to the object the | ||
| 8251 | Item_ref object is referencing. If this replaces the item with a new | ||
| 8252 | one, this object is returned as the result of the compile. | ||
| 8253 | Otherwise we apply the transformer to the Item_ref object itself. | ||
| 8254 | */ | ||
| 8255 | |||
| 8256 | 585156 | Item *Item_ref::compile(Item_analyzer analyzer, uchar **arg_p, | |
| 8257 | Item_transformer transformer, uchar *arg_t) { | ||
| 8258 |
4/4✓ Branch 0 taken 386574 times.
✓ Branch 1 taken 198582 times.
✓ Branch 2 taken 189605 times.
✓ Branch 3 taken 395551 times.
|
585156 | if (!(this->*analyzer)(arg_p)) return this; |
| 8259 | |||
| 8260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 395551 times.
|
395551 | assert((*ref) != nullptr); |
| 8261 | 395551 | Item *new_item = (*ref)->compile(analyzer, arg_p, transformer, arg_t); | |
| 8262 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 395551 times.
|
395551 | if (new_item == nullptr) return nullptr; |
| 8263 | |||
| 8264 | /* | ||
| 8265 | If the object is compiled into a new object, discard the Item_ref | ||
| 8266 | object and return the new object as result. | ||
| 8267 | */ | ||
| 8268 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 395542 times.
|
395551 | if (new_item != *ref) return new_item; |
| 8269 | |||
| 8270 |
2/2✓ Branch 0 taken 200095 times.
✓ Branch 1 taken 195447 times.
|
395542 | return (this->*transformer)(arg_t); |
| 8271 | } | ||
| 8272 | |||
| 8273 | 10349 | void Item_ref::print(const THD *thd, String *str, | |
| 8274 | enum_query_type query_type) const { | ||
| 8275 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10341 times.
|
10349 | if (ref == nullptr) // Unresolved reference: print reference |
| 8276 | 8 | return Item_ident::print(thd, str, query_type); | |
| 8277 | |||
| 8278 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | if (m_alias_of_expr && (*ref)->type() != Item::CACHE_ITEM && |
| 8279 |
7/10✓ Branch 0 taken 122 times.
✓ Branch 1 taken 10219 times.
✓ Branch 2 taken 122 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 122 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 122 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 122 times.
✓ Branch 9 taken 10219 times.
|
10463 | ref_type() != VIEW_REF && table_name == nullptr && item_name.ptr()) { |
| 8280 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | Simple_cstring str1 = (*ref)->real_item()->item_name; |
| 8281 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | append_identifier(thd, str, str1.ptr(), str1.length()); |
| 8282 | } else | ||
| 8283 | 10219 | (*ref)->print(thd, str, query_type); | |
| 8284 | } | ||
| 8285 | |||
| 8286 | 23228854 | bool Item_ref::send(Protocol *prot, String *tmp) { | |
| 8287 | 23228854 | return (*ref)->send(prot, tmp); | |
| 8288 | } | ||
| 8289 | |||
| 8290 | 49975 | double Item_ref::val_real() { | |
| 8291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49975 times.
|
49975 | assert(fixed); |
| 8292 | 49975 | double tmp = (*ref)->val_real(); | |
| 8293 | 49975 | null_value = (*ref)->null_value; | |
| 8294 | 49975 | return tmp; | |
| 8295 | } | ||
| 8296 | |||
| 8297 | 313942 | longlong Item_ref::val_int() { | |
| 8298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 313942 times.
|
313942 | assert(fixed); |
| 8299 | 313942 | longlong tmp = (*ref)->val_int(); | |
| 8300 | 313942 | null_value = (*ref)->null_value; | |
| 8301 | 313942 | return tmp; | |
| 8302 | } | ||
| 8303 | |||
| 8304 | 25 | longlong Item_ref::val_time_temporal() { | |
| 8305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | assert(fixed); |
| 8306 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
25 | assert((*ref)->is_temporal() || (*ref)->is_null()); |
| 8307 | 25 | longlong tmp = (*ref)->val_time_temporal(); | |
| 8308 | 25 | null_value = (*ref)->null_value; | |
| 8309 | 25 | return tmp; | |
| 8310 | } | ||
| 8311 | |||
| 8312 | 7338 | longlong Item_ref::val_date_temporal() { | |
| 8313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7338 times.
|
7338 | assert(fixed); |
| 8314 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7338 times.
|
7338 | assert((*ref)->is_temporal()); |
| 8315 | 7338 | longlong tmp = (*ref)->val_date_temporal(); | |
| 8316 | 7338 | null_value = (*ref)->null_value; | |
| 8317 | 7338 | return tmp; | |
| 8318 | } | ||
| 8319 | |||
| 8320 | 791 | bool Item_ref::val_bool() { | |
| 8321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 791 times.
|
791 | assert(fixed); |
| 8322 | 791 | bool tmp = (*ref)->val_bool(); | |
| 8323 | 791 | null_value = (*ref)->null_value; | |
| 8324 | 791 | return tmp; | |
| 8325 | } | ||
| 8326 | |||
| 8327 | 26331368 | String *Item_ref::val_str(String *tmp) { | |
| 8328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26331368 times.
|
26331368 | assert(fixed); |
| 8329 | 26331368 | tmp = (*ref)->val_str(tmp); | |
| 8330 | 26331368 | null_value = (*ref)->null_value; | |
| 8331 | 26331368 | return tmp; | |
| 8332 | } | ||
| 8333 | |||
| 8334 | 1550 | bool Item_ref::val_json(Json_wrapper *result) { | |
| 8335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1550 times.
|
1550 | assert(fixed); |
| 8336 | 1550 | bool ok = (*ref)->val_json(result); | |
| 8337 | 1550 | null_value = (*ref)->null_value; | |
| 8338 | 1550 | return ok; | |
| 8339 | } | ||
| 8340 | |||
| 8341 | 4653 | bool Item_ref::is_null() { | |
| 8342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4653 times.
|
4653 | assert(fixed); |
| 8343 | 4653 | bool tmp = (*ref)->is_null(); | |
| 8344 | 4653 | null_value = (*ref)->null_value; | |
| 8345 | 4653 | return tmp; | |
| 8346 | } | ||
| 8347 | |||
| 8348 | 4170 | bool Item_ref::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) { | |
| 8349 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4170 times.
|
4170 | assert(fixed); |
| 8350 | 4170 | bool result = (*ref)->get_date(ltime, fuzzydate); | |
| 8351 | 4170 | null_value = (*ref)->null_value; | |
| 8352 | 4170 | return result; | |
| 8353 | } | ||
| 8354 | |||
| 8355 | 29297 | my_decimal *Item_ref::val_decimal(my_decimal *decimal_value) { | |
| 8356 | 29297 | my_decimal *val = (*ref)->val_decimal(decimal_value); | |
| 8357 | 29297 | null_value = (*ref)->null_value; | |
| 8358 | 29297 | return val; | |
| 8359 | } | ||
| 8360 | |||
| 8361 | 196107305 | type_conversion_status Item_ref::save_in_field_inner(Field *to, | |
| 8362 | bool no_conversions) { | ||
| 8363 | type_conversion_status res; | ||
| 8364 | 196107305 | res = (*ref)->save_in_field(to, no_conversions); | |
| 8365 | 196107306 | null_value = (*ref)->null_value; | |
| 8366 | 196107306 | return res; | |
| 8367 | } | ||
| 8368 | |||
| 8369 | 800646 | void Item_ref::make_field(Send_field *field) { | |
| 8370 | 800646 | (*ref)->make_field(field); | |
| 8371 | /* Non-zero in case of a view */ | ||
| 8372 |
1/2✓ Branch 0 taken 800646 times.
✗ Branch 1 not taken.
|
800646 | if (item_name.is_set()) field->col_name = item_name.ptr(); |
| 8373 |
2/2✓ Branch 0 taken 800638 times.
✓ Branch 1 taken 8 times.
|
800646 | if (table_name) field->table_name = table_name; |
| 8374 |
2/2✓ Branch 0 taken 795849 times.
✓ Branch 1 taken 4797 times.
|
800646 | if (m_orig_db_name) field->db_name = m_orig_db_name; |
| 8375 |
1/2✓ Branch 0 taken 800646 times.
✗ Branch 1 not taken.
|
800646 | if (m_orig_field_name) field->org_col_name = m_orig_field_name; |
| 8376 |
2/2✓ Branch 0 taken 800638 times.
✓ Branch 1 taken 8 times.
|
800646 | if (m_orig_table_name) field->org_table_name = m_orig_table_name; |
| 8377 | /* | ||
| 8378 | Some connectors expect a schema name that is empty when a view column | ||
| 8379 | is defined over an expression that is not a column reference from a | ||
| 8380 | view or a table. This is used to flag the column as read-only. | ||
| 8381 | */ | ||
| 8382 |
2/2✓ Branch 0 taken 241176 times.
✓ Branch 1 taken 559470 times.
|
800646 | if (real_item()->type() != Item::FIELD_ITEM) field->db_name = ""; |
| 8383 | 800646 | } | |
| 8384 | |||
| 8385 | 2548105 | Item *Item_ref::get_tmp_table_item(THD *thd) { | |
| 8386 |
1/2✓ Branch 0 taken 2548109 times.
✗ Branch 1 not taken.
|
2548105 | DBUG_TRACE; |
| 8387 |
2/2✓ Branch 0 taken 280542 times.
✓ Branch 1 taken 2267567 times.
|
2548109 | if (!result_field) { |
| 8388 |
1/2✓ Branch 0 taken 280542 times.
✗ Branch 1 not taken.
|
280542 | Item *result = (*ref)->get_tmp_table_item(thd); |
| 8389 | 280542 | return result; | |
| 8390 | } | ||
| 8391 | |||
| 8392 |
2/4✓ Branch 0 taken 2267567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2267563 times.
✗ Branch 3 not taken.
|
2267567 | Item_field *item = new Item_field(result_field); |
| 8393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2267563 times.
|
2267563 | if (item == nullptr) return nullptr; |
| 8394 | |||
| 8395 | 2267563 | item->set_orignal_db_name(m_orig_db_name); | |
| 8396 | 2267565 | item->db_name = db_name; | |
| 8397 | 2267565 | item->table_name = table_name; | |
| 8398 |
4/6✓ Branch 0 taken 2267566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2267566 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1545546 times.
✓ Branch 5 taken 722020 times.
|
2267565 | if (real_item()->type() == Item::FIELD_ITEM) |
| 8399 | 1545546 | item->set_original_table_name( | |
| 8400 |
1/2✓ Branch 0 taken 1545546 times.
✗ Branch 1 not taken.
|
1545546 | down_cast<Item_field *>(real_item())->original_table_name()); |
| 8401 | |||
| 8402 | 2267566 | return item; | |
| 8403 | 2548108 | } | |
| 8404 | |||
| 8405 | 47 | void Item_ref_null_helper::print(const THD *thd, String *str, | |
| 8406 | enum_query_type query_type) const { | ||
| 8407 | 47 | str->append(STRING_WITH_LEN("<ref_null_helper>(")); | |
| 8408 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | if (ref) |
| 8409 | 47 | (*ref)->print(thd, str, query_type); | |
| 8410 | else | ||
| 8411 | ✗ | str->append('?'); | |
| 8412 | 47 | str->append(')'); | |
| 8413 | 47 | } | |
| 8414 | |||
| 8415 | ✗ | bool Item_ref::collect_item_field_or_ref_processor(uchar *arg) { | |
| 8416 | ✗ | auto *info = pointer_cast<Collect_item_fields_or_refs *>(arg); | |
| 8417 | ✗ | if (info->is_stopped(this)) return false; | |
| 8418 | ✗ | if (real_item()->type() == Item::FIELD_ITEM) info->m_items->push_back(this); | |
| 8419 | ✗ | info->stop_at(this); | |
| 8420 | ✗ | return false; | |
| 8421 | } | ||
| 8422 | |||
| 8423 | /** | ||
| 8424 | Prepare referenced field then call usual Item_ref::fix_fields . | ||
| 8425 | |||
| 8426 | @param thd Current session. | ||
| 8427 | @param reference reference on reference where this item stored | ||
| 8428 | |||
| 8429 | @retval | ||
| 8430 | false OK | ||
| 8431 | @retval | ||
| 8432 | true Error | ||
| 8433 | */ | ||
| 8434 | |||
| 8435 | ✗ | bool Item_view_ref::fix_fields(THD *thd, Item **reference) { | |
| 8436 | ✗ | assert(*ref); // view field reference must be defined | |
| 8437 | |||
| 8438 | // (*ref)->check_cols() will be made in Item_ref::fix_fields | ||
| 8439 | ✗ | if ((*ref)->fixed) { | |
| 8440 | /* | ||
| 8441 | Underlying Item_field objects may be shared. Make sure that the use | ||
| 8442 | is marked regardless of how many ref items that point to this field. | ||
| 8443 | */ | ||
| 8444 | ✗ | Mark_field mf(thd->mark_used_columns); | |
| 8445 | ✗ | (*ref)->walk(&Item::mark_field_in_map, enum_walk::POSTFIX, (uchar *)&mf); | |
| 8446 | } else { | ||
| 8447 | ✗ | if ((*ref)->fix_fields(thd, ref)) return true; /* purecov: inspected */ | |
| 8448 | } | ||
| 8449 | ✗ | if (super::fix_fields(thd, reference)) return true; | |
| 8450 | |||
| 8451 | ✗ | if (cached_table->is_inner_table_of_outer_join()) { | |
| 8452 | ✗ | set_nullable(true); | |
| 8453 | ✗ | first_inner_table = cached_table->any_outer_leaf_table(); | |
| 8454 | } | ||
| 8455 | ✗ | return false; | |
| 8456 | } | ||
| 8457 | |||
| 8458 | /** | ||
| 8459 | Prepare referenced outer field then call usual Item_ref::fix_fields | ||
| 8460 | |||
| 8461 | @param thd thread handler | ||
| 8462 | @param reference reference on reference where this item stored | ||
| 8463 | |||
| 8464 | @details | ||
| 8465 | The function serves 3 purposes | ||
| 8466 | - adds field to the current select list | ||
| 8467 | - creates an object to use to reference the item (Item_ref) | ||
| 8468 | - fixes reference (Item_ref object) | ||
| 8469 | |||
| 8470 | If a field isn't already on the select list and the base_ref_items array | ||
| 8471 | is provided then it is added to the all_fields list and the pointer to | ||
| 8472 | it is saved in the base_ref_items array. | ||
| 8473 | |||
| 8474 | When the class is chosen it substitutes the original field in the | ||
| 8475 | Item_outer_ref object. | ||
| 8476 | |||
| 8477 | @returns true if error | ||
| 8478 | */ | ||
| 8479 | |||
| 8480 | 138 | bool Item_outer_ref::fix_fields(THD *thd, Item **reference) { | |
| 8481 | /* outer_ref->check_cols() will be made in Item_ref::fix_fields */ | ||
| 8482 |
3/8✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 138 times.
|
138 | if ((*ref) && !(*ref)->fixed && ((*ref)->fix_fields(thd, reference))) |
| 8483 | ✗ | return true; | |
| 8484 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 121 times.
|
138 | if (super::fix_fields(thd, reference)) return true; |
| 8485 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
|
121 | if (!outer_ref) outer_ref = *ref; |
| 8486 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 1 times.
|
121 | if ((*ref)->type() == Item::FIELD_ITEM) |
| 8487 | 120 | table_name = ((Item_field *)outer_ref)->table_name; | |
| 8488 | |||
| 8489 | 121 | Item *item = outer_ref; | |
| 8490 | 121 | Item **item_ref = ref; | |
| 8491 | |||
| 8492 | /* | ||
| 8493 | TODO: this field item already might be present in the select list. | ||
| 8494 | In this case instead of adding new field item we could use an | ||
| 8495 | existing one. The change will lead to less operations for copying fields, | ||
| 8496 | smaller temporary tables and less data passed through filesort. | ||
| 8497 | */ | ||
| 8498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
|
121 | assert(!qualifying->base_ref_items.is_null()); |
| 8499 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | if (!found_in_select_list) { |
| 8500 | /* | ||
| 8501 | Add the field item to the select list of the current select. | ||
| 8502 | If it's needed reset each Item_ref item that refers this field with | ||
| 8503 | a new reference taken from ref_item_array. | ||
| 8504 | */ | ||
| 8505 | 121 | item_ref = qualifying->add_hidden_item(item); | |
| 8506 | /* | ||
| 8507 | Now the item is in the all_fields list, which elements are used to fill | ||
| 8508 | temporary tables created by the optimizer; thus it will be read and must | ||
| 8509 | be marked as such. Outer references are never written to. | ||
| 8510 | */ | ||
| 8511 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | if (item->fixed) { |
| 8512 | 121 | Mark_field mf(MARK_COLUMNS_READ); | |
| 8513 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | item->walk(&Item::mark_field_in_map, enum_walk::POSTFIX, (uchar *)&mf); |
| 8514 | } | ||
| 8515 | } | ||
| 8516 | |||
| 8517 | Item_ref *const new_ref = | ||
| 8518 |
2/4✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
|
121 | new Item_ref(context, item_ref, db_name, table_name, field_name); |
| 8519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
|
121 | if (new_ref == nullptr) return true; /* purecov: inspected */ |
| 8520 | 121 | outer_ref = new_ref; | |
| 8521 | 121 | ref = &outer_ref; | |
| 8522 | |||
| 8523 | 121 | qualifying->select_list_tables |= item->used_tables(); | |
| 8524 | |||
| 8525 | 121 | return false; | |
| 8526 | } | ||
| 8527 | |||
| 8528 | 34 | void Item_outer_ref::fix_after_pullout(Query_block *parent_query_block, | |
| 8529 | Query_block *removed_query_block) { | ||
| 8530 | /* | ||
| 8531 | If this assertion holds, we need not call fix_after_pullout() on both | ||
| 8532 | *ref and outer_ref, and Item_ref::fix_after_pullout() is sufficient. | ||
| 8533 | */ | ||
| 8534 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | assert(*ref == outer_ref); |
| 8535 | |||
| 8536 | 34 | Item_ref::fix_after_pullout(parent_query_block, removed_query_block); | |
| 8537 | 34 | } | |
| 8538 | |||
| 8539 | ✗ | Item *Item_outer_ref::replace_outer_ref(uchar *arg) { | |
| 8540 | ✗ | auto *info = pointer_cast<Item_outer_ref *>(arg); | |
| 8541 | ✗ | if (this == info) return real_item(); | |
| 8542 | ✗ | return this; | |
| 8543 | } | ||
| 8544 | |||
| 8545 | 374028 | void Item_ref::fix_after_pullout(Query_block *parent_query_block, | |
| 8546 | Query_block *removed_query_block) { | ||
| 8547 | 374028 | (*ref)->fix_after_pullout(parent_query_block, removed_query_block); | |
| 8548 | |||
| 8549 | 374028 | Item_ident::fix_after_pullout(parent_query_block, removed_query_block); | |
| 8550 | 374028 | } | |
| 8551 | |||
| 8552 | /** | ||
| 8553 | Compare two view column references for equality. | ||
| 8554 | |||
| 8555 | A view column reference is considered equal to another column | ||
| 8556 | reference if the second one is a view column and if both column | ||
| 8557 | references resolve to the same item. It is assumed that both | ||
| 8558 | items are of the same type. | ||
| 8559 | |||
| 8560 | @param item item to compare with | ||
| 8561 | |||
| 8562 | @retval | ||
| 8563 | true Referenced item is equal to given item | ||
| 8564 | @retval | ||
| 8565 | false otherwise | ||
| 8566 | */ | ||
| 8567 | |||
| 8568 | 643163 | bool Item_view_ref::eq(const Item *item, bool) const { | |
| 8569 |
2/2✓ Branch 0 taken 475118 times.
✓ Branch 1 taken 168045 times.
|
643163 | if (item->type() == REF_ITEM) { |
| 8570 | 475118 | const Item_ref *item_ref = down_cast<const Item_ref *>(item); | |
| 8571 |
1/2✓ Branch 0 taken 475118 times.
✗ Branch 1 not taken.
|
475118 | if (item_ref->ref_type() == VIEW_REF) { |
| 8572 | 475118 | Item *item_ref_ref = *(item_ref->ref); | |
| 8573 | 475118 | return ((*ref)->real_item() == item_ref_ref->real_item()); | |
| 8574 | } | ||
| 8575 | } | ||
| 8576 | 168045 | return false; | |
| 8577 | } | ||
| 8578 | |||
| 8579 | 60882 | longlong Item_view_ref::val_int() { | |
| 8580 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 60842 times.
|
60882 | if (has_null_row()) { |
| 8581 | 40 | null_value = true; | |
| 8582 | 40 | return 0; | |
| 8583 | } | ||
| 8584 | 60842 | return super::val_int(); | |
| 8585 | } | ||
| 8586 | |||
| 8587 | 20289 | double Item_view_ref::val_real() { | |
| 8588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20289 times.
|
20289 | if (has_null_row()) { |
| 8589 | ✗ | null_value = true; | |
| 8590 | ✗ | return 0.0; | |
| 8591 | } | ||
| 8592 | 20289 | return super::val_real(); | |
| 8593 | } | ||
| 8594 | |||
| 8595 | 22719 | my_decimal *Item_view_ref::val_decimal(my_decimal *dec) { | |
| 8596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22719 times.
|
22719 | if (has_null_row()) { |
| 8597 | ✗ | null_value = true; | |
| 8598 | ✗ | return nullptr; | |
| 8599 | } | ||
| 8600 | 22719 | return super::val_decimal(dec); | |
| 8601 | } | ||
| 8602 | |||
| 8603 | 25988927 | String *Item_view_ref::val_str(String *str) { | |
| 8604 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 25988898 times.
|
25988927 | if (has_null_row()) { |
| 8605 | 29 | null_value = true; | |
| 8606 | 29 | return nullptr; | |
| 8607 | } | ||
| 8608 | 25988898 | return super::val_str(str); | |
| 8609 | } | ||
| 8610 | |||
| 8611 | 16 | bool Item_view_ref::val_bool() { | |
| 8612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (has_null_row()) { |
| 8613 | ✗ | null_value = true; | |
| 8614 | ✗ | return false; | |
| 8615 | } | ||
| 8616 | 16 | return super::val_bool(); | |
| 8617 | } | ||
| 8618 | |||
| 8619 | 260 | bool Item_view_ref::val_json(Json_wrapper *wr) { | |
| 8620 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 258 times.
|
260 | if (has_null_row()) { |
| 8621 | 2 | null_value = true; | |
| 8622 | 2 | return false; | |
| 8623 | } | ||
| 8624 | 258 | return super::val_json(wr); | |
| 8625 | } | ||
| 8626 | |||
| 8627 | 8309 | bool Item_view_ref::is_null() { | |
| 8628 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8304 times.
|
8309 | if (has_null_row()) return true; |
| 8629 | |||
| 8630 | 8304 | return (*ref)->is_null(); | |
| 8631 | } | ||
| 8632 | |||
| 8633 | 23229412 | bool Item_view_ref::send(Protocol *prot, String *tmp) { | |
| 8634 |
2/2✓ Branch 0 taken 566 times.
✓ Branch 1 taken 23228846 times.
|
23229412 | if (has_null_row()) return prot->store_null(); |
| 8635 | 23228846 | return super::send(prot, tmp); | |
| 8636 | } | ||
| 8637 | |||
| 8638 | 196104576 | type_conversion_status Item_view_ref::save_in_field_inner(Field *field, | |
| 8639 | bool no_conversions) { | ||
| 8640 |
2/2✓ Branch 0 taken 155 times.
✓ Branch 1 taken 196104421 times.
|
196104576 | if (has_null_row()) |
| 8641 | 155 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 8642 | |||
| 8643 | 196104421 | return super::save_in_field_inner(field, no_conversions); | |
| 8644 | } | ||
| 8645 | |||
| 8646 | ✗ | bool Item_view_ref::collect_item_field_or_view_ref_processor(uchar *arg) { | |
| 8647 | ✗ | auto *info = pointer_cast<Collect_item_fields_or_view_refs *>(arg); | |
| 8648 | ✗ | if (info->is_stopped(this)) return false; | |
| 8649 | // We collect this view ref | ||
| 8650 | // (1) If its qualifying table is in the transformed query block | ||
| 8651 | // (2) If its underlying field's qualifying table is in the transformed | ||
| 8652 | // query block | ||
| 8653 | // (3) If this view ref is an outer reference dependent on the | ||
| 8654 | // transformed query block | ||
| 8655 | ✗ | Item *item = nullptr; | |
| 8656 | ✗ | item = (context->query_block == info->m_transformed_block) // 1 | |
| 8657 | ✗ | ? this | |
| 8658 | ✗ | : ((real_item()->type() == Item::FIELD_ITEM && | |
| 8659 | ✗ | (down_cast<Item_field *>(real_item())->context->query_block == | |
| 8660 | ✗ | info->m_transformed_block)) // 2 | |
| 8661 | ✗ | ? this->real_item() | |
| 8662 | ✗ | : ((depended_from == info->m_transformed_block) // 3 | |
| 8663 | ✗ | ? this | |
| 8664 | : nullptr)); | ||
| 8665 | ✗ | if (item != nullptr) info->m_item_fields_or_view_refs->push_back(item); | |
| 8666 | ✗ | info->stop_at(this); | |
| 8667 | ✗ | return false; | |
| 8668 | } | ||
| 8669 | |||
| 8670 | ✗ | Item *Item_view_ref::replace_item_view_ref(uchar *arg) { | |
| 8671 | ✗ | auto *info = pointer_cast<Item::Item_view_ref_replacement *>(arg); | |
| 8672 | ✗ | Item *real_item = Item_ref::real_item(); | |
| 8673 | ✗ | if (real_item == info->m_target) { | |
| 8674 | Item_field *new_field = | ||
| 8675 | ✗ | new (current_thd->mem_root) Item_field(info->m_field); | |
| 8676 | ✗ | if (new_field == nullptr) return nullptr; | |
| 8677 | // Set correct metadata for the new field incl. any alias. | ||
| 8678 | ✗ | if (orig_name.length() != 0) { | |
| 8679 | // The one moved to new_derived has its orig_name set | ||
| 8680 | ✗ | new_field->item_name.set(orig_name.ptr()); | |
| 8681 | ✗ | new_field->orig_name.set(orig_name.ptr()); | |
| 8682 | } else { | ||
| 8683 | // this is a duplicated view reference, not touched yet. | ||
| 8684 | ✗ | new_field->item_name.set(item_name.ptr()); | |
| 8685 | ✗ | new_field->orig_name.set(item_name.ptr()); | |
| 8686 | } | ||
| 8687 | ✗ | if (info->m_curr_block == info->m_trans_block) { | |
| 8688 | ✗ | return new_field; | |
| 8689 | } | ||
| 8690 | |||
| 8691 | // The is an outer reference, so we cannot reuse transformed query | ||
| 8692 | // block's Item_field; make a new one for this query block | ||
| 8693 | ✗ | new_field->depended_from = info->m_trans_block; | |
| 8694 | ✗ | new_field->context = &info->m_curr_block->context; | |
| 8695 | ✗ | return new_field; | |
| 8696 | } | ||
| 8697 | ✗ | return this; | |
| 8698 | } | ||
| 8699 | |||
| 8700 | 49 | Item *Item_view_ref::replace_view_refs_with_clone(uchar *arg) { | |
| 8701 | Condition_pushdown::Derived_table_info *dti = | ||
| 8702 | 49 | pointer_cast<Condition_pushdown::Derived_table_info *>(arg); | |
| 8703 | |||
| 8704 | // Replace the view ref with a clone to the referenced item. | ||
| 8705 | // We use a different context to resolve the clone from that of | ||
| 8706 | // the derived table context. | ||
| 8707 | // For Ex: | ||
| 8708 | // SELECT * FROM | ||
| 8709 | // (SELECT f1 FROM (SELECT f1 FROM t1 GROUP BY f1) AS dt1) AS dt2 | ||
| 8710 | // WHERE f1 > 3 GROUP BY f1; | ||
| 8711 | // Here dt2 gets merged with the outer query block. As a result, "f1" | ||
| 8712 | // in the outer query block (in select list, where clause and group by) | ||
| 8713 | // will be a view reference. The underlying field for all three | ||
| 8714 | // view references is shared. Therefore, when "f1>3" needs to be | ||
| 8715 | // pushed down to dt1, we need to clone the referenced item (dt2.f1). | ||
| 8716 | // Since the query block having dt2 is merged with the outer query | ||
| 8717 | // block, the context to resolve the field will be different than | ||
| 8718 | // the derived table context (dt1). | ||
| 8719 | 49 | return dti->m_derived_query_block->outer_query_block()->clone_expression( | |
| 8720 | 49 | current_thd, *ref, | |
| 8721 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 43 times.
|
55 | (dti->m_derived_table->is_system_view || |
| 8722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | (dti->m_derived_table->referencing_view && |
| 8723 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
49 | dti->m_derived_table->referencing_view->is_system_view))); |
| 8724 | } | ||
| 8725 | |||
| 8726 | 5540 | bool Item_default_value::itemize(Parse_context *pc, Item **res) { | |
| 8727 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5540 times.
|
5540 | if (skip_itemize(res)) return false; |
| 8728 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5540 times.
|
5540 | if (super::itemize(pc, res)) return true; |
| 8729 | |||
| 8730 |
2/2✓ Branch 0 taken 59 times.
✓ Branch 1 taken 5481 times.
|
5540 | if (arg != nullptr) { |
| 8731 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (arg->itemize(pc, &arg)) return true; |
| 8732 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 58 times.
|
59 | if (arg->is_splocal()) { |
| 8733 | 1 | Item_splocal *il = static_cast<Item_splocal *>(arg); | |
| 8734 | |||
| 8735 | 1 | my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->m_name.ptr()); | |
| 8736 | 1 | return true; | |
| 8737 | } | ||
| 8738 | } | ||
| 8739 | 5539 | return false; | |
| 8740 | } | ||
| 8741 | |||
| 8742 | ✗ | bool Item_default_value::eq(const Item *item, bool binary_cmp) const { | |
| 8743 | ✗ | return item->type() == DEFAULT_VALUE_ITEM && | |
| 8744 | ✗ | down_cast<const Item_default_value *>(item)->arg->eq(arg, binary_cmp); | |
| 8745 | } | ||
| 8746 | |||
| 8747 | 5451 | bool Item_default_value::fix_fields(THD *thd, Item **) { | |
| 8748 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5451 times.
|
5451 | assert(!fixed); |
| 8749 | |||
| 8750 | Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler( | ||
| 8751 |
1/2✓ Branch 0 taken 5451 times.
✗ Branch 1 not taken.
|
5451 | thd, context->view_error_handler, context->view_error_handler_arg); |
| 8752 |
2/2✓ Branch 0 taken 5410 times.
✓ Branch 1 taken 41 times.
|
5451 | if (arg == nullptr) { |
| 8753 | 5410 | fixed = true; | |
| 8754 | 5410 | return false; | |
| 8755 | } | ||
| 8756 |
4/8✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 41 times.
|
41 | if (!arg->fixed && arg->fix_fields(thd, &arg)) return true; |
| 8757 | |||
| 8758 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | Item *const real_arg = arg->real_item(); |
| 8759 |
2/4✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
|
41 | if (real_arg->type() != FIELD_ITEM) { |
| 8760 | ✗ | my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->item_name.ptr()); | |
| 8761 | ✗ | return true; | |
| 8762 | } | ||
| 8763 | |||
| 8764 | 41 | Item_field *const field_arg = down_cast<Item_field *>(real_arg); | |
| 8765 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 35 times.
|
41 | if (field_arg->field->is_flag_set(NO_DEFAULT_VALUE_FLAG)) { |
| 8766 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name); |
| 8767 | 6 | return true; | |
| 8768 | } | ||
| 8769 | |||
| 8770 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 19 times.
|
35 | if (field_arg->field->has_insert_default_general_value_expression()) { |
| 8771 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | my_error(ER_DEFAULT_AS_VAL_GENERATED, MYF(0)); |
| 8772 | 16 | return true; | |
| 8773 | } | ||
| 8774 | |||
| 8775 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | Field *const def_field = field_arg->field->clone(thd->mem_root); |
| 8776 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if (def_field == nullptr) return true; |
| 8777 | |||
| 8778 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | def_field->move_field_offset(def_field->table->default_values_offset()); |
| 8779 | 19 | m_rowbuffer_saved = def_field->table->s->default_values; | |
| 8780 | |||
| 8781 | // Assign the cloned field as the one to use hereafter | ||
| 8782 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | set_field(def_field); |
| 8783 | |||
| 8784 | // Needs cached_table for some Item traversal functions: | ||
| 8785 | 19 | cached_table = table_ref; | |
| 8786 | |||
| 8787 | // Use same field name as the underlying field: | ||
| 8788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | assert(field_name == nullptr); |
| 8789 | 19 | field_name = arg->item_name.ptr(); | |
| 8790 | |||
| 8791 | // Always allow a "read" from the default value. | ||
| 8792 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | field->table->mark_column_used(field, MARK_COLUMNS_READ); |
| 8793 | |||
| 8794 | 19 | return false; | |
| 8795 | 5451 | } | |
| 8796 | |||
| 8797 | 7144 | void Item_default_value::bind_fields() { | |
| 8798 |
3/4✓ Branch 0 taken 7144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7140 times.
✓ Branch 3 taken 4 times.
|
7144 | if (!fixed || arg == nullptr) return; |
| 8799 | |||
| 8800 | 4 | field->move_field_offset( | |
| 8801 | 4 | (ptrdiff_t)(field->table->s->default_values - m_rowbuffer_saved)); | |
| 8802 | 4 | m_rowbuffer_saved = field->table->s->default_values; | |
| 8803 | // Always allow a "read" from the default value. | ||
| 8804 | 4 | field->table->mark_column_used(field, MARK_COLUMNS_READ); | |
| 8805 | } | ||
| 8806 | |||
| 8807 | 14 | void Item_default_value::print(const THD *thd, String *str, | |
| 8808 | enum_query_type query_type) const { | ||
| 8809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (!arg) { |
| 8810 | ✗ | str->append(STRING_WITH_LEN("default")); | |
| 8811 | ✗ | return; | |
| 8812 | } | ||
| 8813 | 14 | str->append(STRING_WITH_LEN("default(")); | |
| 8814 | 14 | arg->print(thd, str, query_type); | |
| 8815 | 14 | str->append(')'); | |
| 8816 | } | ||
| 8817 | |||
| 8818 | 3702 | type_conversion_status Item_default_value::save_in_field_inner( | |
| 8819 | Field *field_arg, bool no_conversions) { | ||
| 8820 | 3702 | THD *thd = current_thd; | |
| 8821 |
2/2✓ Branch 0 taken 3692 times.
✓ Branch 1 taken 10 times.
|
3702 | if (!arg) { |
| 8822 | 3692 | if ((field_arg->is_flag_set(NO_DEFAULT_VALUE_FLAG) && | |
| 8823 |
5/6✓ Branch 0 taken 38 times.
✓ Branch 1 taken 3654 times.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35 times.
✓ Branch 5 taken 3657 times.
|
3730 | field_arg->m_default_val_expr == nullptr) && |
| 8824 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
|
38 | field_arg->real_type() != MYSQL_TYPE_ENUM) { |
| 8825 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
|
35 | if (field_arg->reset()) { |
| 8826 | 1 | my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0)); | |
| 8827 | 1 | return TYPE_ERR_BAD_VALUE; | |
| 8828 | } | ||
| 8829 | |||
| 8830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (context->view_error_handler) { |
| 8831 | ✗ | TABLE_LIST *view = cached_table->top_table(); | |
| 8832 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 8833 | ER_NO_DEFAULT_FOR_VIEW_FIELD, | ||
| 8834 | ER_THD(thd, ER_NO_DEFAULT_FOR_VIEW_FIELD), view->db, | ||
| 8835 | view->table_name); | ||
| 8836 | } else { | ||
| 8837 | 34 | push_warning_printf( | |
| 8838 | thd, Sql_condition::SL_WARNING, ER_NO_DEFAULT_FOR_FIELD, | ||
| 8839 | ER_THD(thd, ER_NO_DEFAULT_FOR_FIELD), field_arg->field_name); | ||
| 8840 | } | ||
| 8841 | 34 | return TYPE_ERR_BAD_VALUE; | |
| 8842 | } | ||
| 8843 | |||
| 8844 | // If this DEFAULT's value is actually an expression, mark the columns | ||
| 8845 | // it uses for reading. For inserts where the name is not explicitly | ||
| 8846 | // mentioned, this is set in COPY_INFO::get_function_default_columns | ||
| 8847 |
2/2✓ Branch 0 taken 253 times.
✓ Branch 1 taken 3404 times.
|
3657 | if (field_arg->has_insert_default_general_value_expression()) { |
| 8848 |
2/2✓ Branch 0 taken 517 times.
✓ Branch 1 taken 253 times.
|
770 | for (uint j = 0; j < field_arg->table->s->fields; j++) { |
| 8849 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 325 times.
|
517 | if (bitmap_is_set(&field_arg->m_default_val_expr->base_columns_map, |
| 8850 | j)) { | ||
| 8851 | 192 | bitmap_set_bit(field_arg->table->read_set, j); | |
| 8852 | } | ||
| 8853 | } | ||
| 8854 | } | ||
| 8855 | |||
| 8856 | 3657 | field_arg->set_default(); | |
| 8857 | 3657 | return field_arg->validate_stored_val(current_thd); | |
| 8858 | } | ||
| 8859 | 10 | return Item_field::save_in_field_inner(field_arg, no_conversions); | |
| 8860 | } | ||
| 8861 | |||
| 8862 | 10 | Item *Item_default_value::transform(Item_transformer transformer, uchar *args) { | |
| 8863 | /* | ||
| 8864 | If the value of arg is NULL, then this object represents a constant, | ||
| 8865 | so further transformation is unnecessary (and impossible). | ||
| 8866 | */ | ||
| 8867 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
|
10 | if (arg == nullptr) return this; |
| 8868 | |||
| 8869 | 1 | Item *new_item = arg->transform(transformer, args); | |
| 8870 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (new_item == nullptr) return nullptr; /* purecov: inspected */ |
| 8871 | |||
| 8872 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return (this->*transformer)(args); |
| 8873 | } | ||
| 8874 | |||
| 8875 | 4 | bool Item_insert_value::eq(const Item *item, bool binary_cmp) const { | |
| 8876 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | return item->type() == INSERT_VALUE_ITEM && |
| 8877 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
4 | (down_cast<const Item_insert_value *>(item))->arg->eq(arg, binary_cmp); |
| 8878 | } | ||
| 8879 | |||
| 8880 | 99 | bool Item_insert_value::fix_fields(THD *thd, Item **reference) { | |
| 8881 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
99 | assert(!fixed); |
| 8882 | // Argument must be resolved from first table | ||
| 8883 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 47 times.
|
99 | if (!arg->fixed) { |
| 8884 | 52 | TABLE_LIST *orig_next_table = context->last_name_resolution_table; | |
| 8885 | 52 | context->last_name_resolution_table = context->first_name_resolution_table; | |
| 8886 | 52 | bool res = arg->fix_fields(thd, &arg); | |
| 8887 | 52 | context->last_name_resolution_table = orig_next_table; | |
| 8888 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 51 times.
|
52 | if (res) return true; |
| 8889 | } | ||
| 8890 | |||
| 8891 | 98 | arg = arg->real_item(); | |
| 8892 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 94 times.
|
98 | if (arg->type() != FIELD_ITEM) { |
| 8893 | 4 | my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function"); | |
| 8894 | 4 | return true; | |
| 8895 | } | ||
| 8896 | |||
| 8897 | 94 | Item_field *field_arg = down_cast<Item_field *>(arg); | |
| 8898 | |||
| 8899 |
2/2✓ Branch 0 taken 92 times.
✓ Branch 1 taken 2 times.
|
94 | if (thd->lex->in_update_value_clause && |
| 8900 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 1 times.
|
92 | field_arg->field->table->insert_values) { |
| 8901 | 91 | Field *def_field = field_arg->field->clone(thd->mem_root); | |
| 8902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
|
91 | if (def_field == nullptr) return true; |
| 8903 | |||
| 8904 | 91 | def_field->move_field_offset((ptrdiff_t)(def_field->table->insert_values - | |
| 8905 | 91 | def_field->table->record[0])); | |
| 8906 | 91 | m_rowbuffer_saved = def_field->table->insert_values; | |
| 8907 | /* | ||
| 8908 | Put the original and cloned Field_blob objects in | ||
| 8909 | 'insert_update_values_map' map. This will be used to make a | ||
| 8910 | separate copy of blob value, in case 'UPDATE' clause is executed in | ||
| 8911 | 'INSERT...UPDATE' statement. See mysql_prepare_blob_values() | ||
| 8912 | for more info. We are only checking for MYSQL_TYPE_BLOB and | ||
| 8913 | MYSQL_TYPE_GEOMETRY. Sub types of blob like TINY BLOB, LONG BLOB, JSON, | ||
| 8914 | are internally stored are BLOB only. Same applies to geometry type. | ||
| 8915 | */ | ||
| 8916 |
4/4✓ Branch 0 taken 87 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 87 times.
|
178 | if ((def_field->type() == MYSQL_TYPE_BLOB || |
| 8917 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
|
87 | def_field->type() == MYSQL_TYPE_GEOMETRY)) { |
| 8918 | try { | ||
| 8919 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | thd->lex->insert_values_map(field_arg, def_field); |
| 8920 | ✗ | } catch (std::bad_alloc const &) { | |
| 8921 | ✗ | my_error(ER_STD_BAD_ALLOC_ERROR, MYF(0), "", "fix_fields"); | |
| 8922 | ✗ | return true; | |
| 8923 | } | ||
| 8924 | } | ||
| 8925 | |||
| 8926 | 91 | set_field(def_field); | |
| 8927 | |||
| 8928 | // Use same field name as the underlying field: | ||
| 8929 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
|
91 | assert(field_name == nullptr); |
| 8930 | 91 | field_name = arg->item_name.ptr(); | |
| 8931 | |||
| 8932 | // The VALUES function is deprecated. | ||
| 8933 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 47 times.
|
91 | if (m_is_values_function) |
| 8934 | 44 | push_deprecated_warn( | |
| 8935 | thd, "VALUES function", | ||
| 8936 | "an alias (INSERT INTO ... VALUES (...) AS alias) and replace " | ||
| 8937 | "VALUES(col) in the ON DUPLICATE KEY UPDATE clause with alias.col"); | ||
| 8938 | 91 | } else { | |
| 8939 | // VALUES() is used out-of-scope - its value is always NULL | ||
| 8940 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | Item *const item = new Item_null(this->item_name); |
| 8941 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (item == nullptr) return true; |
| 8942 | 3 | *reference = item; | |
| 8943 | |||
| 8944 | // Ensure the object is not handled by bind_fields() | ||
| 8945 | 3 | arg = nullptr; | |
| 8946 | |||
| 8947 | // The VALUES function is deprecated. It always returns NULL in this | ||
| 8948 | // context, but if it is inside an ON DUPLICATE KEY UPDATE clause, the user | ||
| 8949 | // probably meant something else. In that case, suggest an alternative | ||
| 8950 | // syntax which doesn't always return NULL. | ||
| 8951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(m_is_values_function); |
| 8952 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (thd->lex->in_update_value_clause) { |
| 8953 | 1 | push_warning(thd, Sql_condition::SL_WARNING, ER_WARN_DEPRECATED_SYNTAX, | |
| 8954 | ER_THD(thd, ER_WARN_DEPRECATED_VALUES_FUNCTION_ALWAYS_NULL)); | ||
| 8955 | } else { | ||
| 8956 | 2 | push_deprecated_warn_no_replacement(thd, "VALUES function"); | |
| 8957 | } | ||
| 8958 | } | ||
| 8959 | 94 | return false; | |
| 8960 | } | ||
| 8961 | |||
| 8962 | 1014 | void Item_insert_value::bind_fields() { | |
| 8963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1014 times.
|
1014 | if (arg == nullptr) return; |
| 8964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1014 times.
|
1014 | if (!fixed) return; |
| 8965 | |||
| 8966 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1014 times.
|
1014 | assert(table_ref->table->insert_values); |
| 8967 | |||
| 8968 | // Bind field to the current TABLE object | ||
| 8969 | 1014 | field->table = table_ref->table; | |
| 8970 | |||
| 8971 | 1014 | field->move_field_offset( | |
| 8972 | 1014 | (ptrdiff_t)(field->table->insert_values - m_rowbuffer_saved)); | |
| 8973 | 1014 | m_rowbuffer_saved = field->table->insert_values; | |
| 8974 | |||
| 8975 | 1014 | Item_field *field_arg = down_cast<Item_field *>(arg->real_item()); | |
| 8976 |
4/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 999 times.
✓ Branch 2 taken 999 times.
✓ Branch 3 taken 15 times.
|
1029 | if ((field->type() == MYSQL_TYPE_BLOB || |
| 8977 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | field->type() == MYSQL_TYPE_GEOMETRY)) { |
| 8978 | 999 | current_thd->lex->insert_values_map(field_arg, field); | |
| 8979 | } | ||
| 8980 | |||
| 8981 | 1014 | set_result_field(field); | |
| 8982 | } | ||
| 8983 | |||
| 8984 | 1124 | void Item_insert_value::cleanup() { | |
| 8985 | // Disconnect from the TABLE object | ||
| 8986 |
2/2✓ Branch 0 taken 1105 times.
✓ Branch 1 taken 19 times.
|
1124 | if (field != nullptr) field->table = nullptr; |
| 8987 | 1124 | Item::cleanup(); | |
| 8988 | 1124 | } | |
| 8989 | |||
| 8990 | ✗ | void Item_insert_value::print(const THD *thd, String *str, | |
| 8991 | enum_query_type query_type) const { | ||
| 8992 | ✗ | str->append(STRING_WITH_LEN("values(")); | |
| 8993 | ✗ | arg->print(thd, str, query_type); | |
| 8994 | ✗ | str->append(')'); | |
| 8995 | } | ||
| 8996 | |||
| 8997 | /** | ||
| 8998 | Find index of Field object which will be appropriate for item | ||
| 8999 | representing field of row being changed in trigger. | ||
| 9000 | |||
| 9001 | @param table_triggers Table_trigger_field_support instance. Do not use | ||
| 9002 | TABLE::triggers as it might be not initialized at | ||
| 9003 | the moment. | ||
| 9004 | @param table_grant_info GRANT_INFO of the subject table | ||
| 9005 | |||
| 9006 | @note | ||
| 9007 | This function does almost the same as fix_fields() for Item_field but is | ||
| 9008 | invoked right after trigger definition parsing. Since at this stage we can't | ||
| 9009 | say exactly what Field object (corresponding to TABLE::record[0] or | ||
| 9010 | TABLE::record[1]) should be bound to this Item, we only find out index of | ||
| 9011 | the Field and then select concrete Field object in fix_fields() (by that | ||
| 9012 | time Table_trigger_dispatcher::old_field/ new_field should point to proper | ||
| 9013 | array of Fields). It also binds Item_trigger_field to | ||
| 9014 | Table_trigger_field_support object for table of trigger which uses this | ||
| 9015 | item. | ||
| 9016 | Another difference is that the field is not marked in read_set/write_set. | ||
| 9017 | */ | ||
| 9018 | |||
| 9019 | 49063 | void Item_trigger_field::setup_field( | |
| 9020 | Table_trigger_field_support *table_triggers, GRANT_INFO *table_grant_info) { | ||
| 9021 | /* | ||
| 9022 | Try to find field by its name and if it will be found | ||
| 9023 | set field_idx properly. | ||
| 9024 | */ | ||
| 9025 | 49063 | (void)find_field_in_table(table_triggers->get_subject_table(), field_name, | |
| 9026 | false, &field_idx); | ||
| 9027 | 49064 | triggers = table_triggers; | |
| 9028 | 49064 | table_grants = table_grant_info; | |
| 9029 | 49064 | } | |
| 9030 | |||
| 9031 | 17 | bool Item_trigger_field::eq(const Item *item, bool) const { | |
| 9032 | 17 | return item->type() == TRIGGER_FIELD_ITEM && | |
| 9033 | 16 | trigger_var_type == | |
| 9034 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
33 | down_cast<const Item_trigger_field *>(item)->trigger_var_type && |
| 9035 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
33 | !my_strcasecmp( |
| 9036 | system_charset_info, field_name, | ||
| 9037 | down_cast<const Item_trigger_field *>(item)->field_name); | ||
| 9038 | } | ||
| 9039 | |||
| 9040 | 6590 | bool Item_trigger_field::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it) { | |
| 9041 | 6590 | Item *item = sp_prepare_func_item(thd, it); | |
| 9042 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6585 times.
|
6590 | if (item == nullptr) return true; |
| 9043 | |||
| 9044 |
2/2✓ Branch 0 taken 1313 times.
✓ Branch 1 taken 5272 times.
|
6585 | if (!fixed) { |
| 9045 |
1/2✓ Branch 0 taken 1313 times.
✗ Branch 1 not taken.
|
1313 | Prepared_stmt_arena_holder ps_arena_holder(thd); |
| 9046 | |||
| 9047 |
3/4✓ Branch 0 taken 1313 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 1287 times.
|
1313 | if (fix_fields(thd, nullptr)) return true; |
| 9048 |
2/2✓ Branch 0 taken 1287 times.
✓ Branch 1 taken 26 times.
|
1313 | } else { |
| 9049 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5264 times.
|
5272 | if (walk(&Item::check_column_privileges, enum_walk::PREFIX, |
| 9050 | pointer_cast<uchar *>(thd))) | ||
| 9051 | 8 | return true; | |
| 9052 | } | ||
| 9053 | |||
| 9054 | // NOTE: field->table->copy_blobs should be false here, but let's | ||
| 9055 | // remember the value at runtime to avoid subtle bugs. | ||
| 9056 | 6551 | bool copy_blobs_saved = field->table->copy_blobs; | |
| 9057 | |||
| 9058 | 6551 | field->table->copy_blobs = true; | |
| 9059 | |||
| 9060 | 6551 | int err_code = item->save_in_field(field, false); | |
| 9061 | |||
| 9062 | 6551 | field->table->copy_blobs = copy_blobs_saved; | |
| 9063 | |||
| 9064 | 6551 | return err_code < 0; | |
| 9065 | } | ||
| 9066 | |||
| 9067 | 14706 | bool Item_trigger_field::fix_fields(THD *thd, Item **) { | |
| 9068 | /* | ||
| 9069 | Since trigger is object tightly associated with TABLE object most | ||
| 9070 | of its set up can be performed during trigger loading i.e. trigger | ||
| 9071 | parsing! So we have little to do in fix_fields. :) | ||
| 9072 | */ | ||
| 9073 | |||
| 9074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14706 times.
|
14706 | assert(fixed == 0); |
| 9075 | |||
| 9076 | /* Set field. */ | ||
| 9077 | |||
| 9078 |
2/2✓ Branch 0 taken 14676 times.
✓ Branch 1 taken 30 times.
|
14706 | if (field_idx != (uint)-1) { |
| 9079 | /* | ||
| 9080 | Check access privileges for the subject table. We check privileges only | ||
| 9081 | in runtime. | ||
| 9082 | */ | ||
| 9083 | |||
| 9084 |
2/2✓ Branch 0 taken 8303 times.
✓ Branch 1 taken 6373 times.
|
14676 | if (table_grants) { |
| 9085 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8255 times.
|
16606 | if (check_grant_column( |
| 9086 | 8303 | thd, table_grants, triggers->get_subject_table()->s->db.str, | |
| 9087 | 8303 | triggers->get_subject_table()->s->table_name.str, field_name, | |
| 9088 | strlen(field_name), thd->security_context(), want_privilege)) | ||
| 9089 | 48 | return true; | |
| 9090 | } | ||
| 9091 | |||
| 9092 | 14628 | field = triggers->get_trigger_variable_field(trigger_var_type, field_idx); | |
| 9093 | |||
| 9094 | 14628 | set_field(field); | |
| 9095 | 14628 | return false; | |
| 9096 | } | ||
| 9097 | |||
| 9098 | 30 | my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name, | |
| 9099 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
|
30 | (trigger_var_type == TRG_NEW_ROW) ? "NEW" : "OLD"); |
| 9100 | 30 | return true; | |
| 9101 | } | ||
| 9102 | |||
| 9103 | 57432 | void Item_trigger_field::bind_fields() { | |
| 9104 | // Triggers are tied to a TABLE, so fields will never relocate. | ||
| 9105 | |||
| 9106 |
2/2✓ Branch 0 taken 2238 times.
✓ Branch 1 taken 55194 times.
|
57432 | if (!fixed) return; |
| 9107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55194 times.
|
55194 | assert(field_idx != (uint)-1); |
| 9108 | |||
| 9109 | /* | ||
| 9110 | If the trigger's substatement using this object was previously invoked by a | ||
| 9111 | calling statement, and is now invoked by another, it may be that the two | ||
| 9112 | callers put the "old" record in a different place (for example, for a DELETE | ||
| 9113 | trigger, REPLACE uses TABLE::record[1] while DELETE uses TABLE::record[0], | ||
| 9114 | see the argument old_row_is_record1 in | ||
| 9115 | Table_trigger_dispatcher::process_triggers()). Thus 'field' needs an update | ||
| 9116 | for the second caller. | ||
| 9117 | */ | ||
| 9118 | |||
| 9119 | 55194 | field = triggers->get_trigger_variable_field(trigger_var_type, field_idx); | |
| 9120 | |||
| 9121 | 55194 | set_field(field); | |
| 9122 | } | ||
| 9123 | |||
| 9124 | 39377 | bool Item_trigger_field::check_column_privileges(uchar *arg) { | |
| 9125 | 39377 | THD *const thd = pointer_cast<THD *>(arg); | |
| 9126 | 39377 | TABLE *table = triggers->get_subject_table(); | |
| 9127 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 39368 times.
|
78754 | if (check_grant_column(thd, table_grants, table->s->db.str, |
| 9128 | 39377 | table->s->table_name.str, field_name, | |
| 9129 | strlen(field_name), thd->security_context(), | ||
| 9130 | want_privilege)) | ||
| 9131 | 9 | return true; | |
| 9132 | 39368 | return false; | |
| 9133 | } | ||
| 9134 | |||
| 9135 | 8 | void Item_trigger_field::print(const THD *, String *str, | |
| 9136 | enum_query_type) const { | ||
| 9137 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | str->append((trigger_var_type == TRG_NEW_ROW) ? "NEW" : "OLD", 3); |
| 9138 | 8 | str->append('.'); | |
| 9139 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | str->append(field_name); |
| 9140 | 8 | } | |
| 9141 | |||
| 9142 | 63551 | void Item_trigger_field::cleanup() { | |
| 9143 | /* | ||
| 9144 | A trigger is bound to a TABLE, so the TABLE_LIST may vary between executions | ||
| 9145 | */ | ||
| 9146 | 63551 | table_ref = nullptr; | |
| 9147 | |||
| 9148 | 63551 | Item::cleanup(); | |
| 9149 | 63551 | } | |
| 9150 | |||
| 9151 | 165345057 | Item_result item_cmp_type(Item_result a, Item_result b) { | |
| 9152 |
2/2✓ Branch 0 taken 165147816 times.
✓ Branch 1 taken 197241 times.
|
165345057 | if (a == b) { |
| 9153 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 165147816 times.
|
165147816 | assert(a != INVALID_RESULT); |
| 9154 | 165147816 | return a; | |
| 9155 |
3/4✓ Branch 0 taken 197250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 197234 times.
|
197241 | } else if (a == ROW_RESULT || b == ROW_RESULT) { |
| 9156 | 7 | return ROW_RESULT; | |
| 9157 | } | ||
| 9158 |
6/6✓ Branch 0 taken 114168 times.
✓ Branch 1 taken 83066 times.
✓ Branch 2 taken 47005 times.
✓ Branch 3 taken 67163 times.
✓ Branch 4 taken 84662 times.
✓ Branch 5 taken 45409 times.
|
197234 | if ((a == INT_RESULT || a == DECIMAL_RESULT) && |
| 9159 |
2/2✓ Branch 0 taken 4590 times.
✓ Branch 1 taken 80072 times.
|
84662 | (b == INT_RESULT || b == DECIMAL_RESULT)) { |
| 9160 | 49999 | return DECIMAL_RESULT; | |
| 9161 | } | ||
| 9162 | 147235 | return REAL_RESULT; | |
| 9163 | } | ||
| 9164 | |||
| 9165 | /** | ||
| 9166 | Substitute a const item with a simpler const item, if possible. | ||
| 9167 | |||
| 9168 | @param thd Current session. | ||
| 9169 | @param[in,out] ref Const item to be processed, contains simplest possible | ||
| 9170 | item on return. | ||
| 9171 | @param comp_item Item that provides result type for generated const item | ||
| 9172 | |||
| 9173 | @returns false if success, true if error | ||
| 9174 | */ | ||
| 9175 | |||
| 9176 | 150733 | bool resolve_const_item(THD *thd, Item **ref, Item *comp_item) { | |
| 9177 | 150733 | Item *item = *ref; | |
| 9178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150733 times.
|
150733 | assert(item->const_item()); |
| 9179 | |||
| 9180 | 150733 | Item *new_item = nullptr; | |
| 9181 |
2/2✓ Branch 0 taken 150316 times.
✓ Branch 1 taken 417 times.
|
150733 | if (item->basic_const_item()) return false; // Can't be better |
| 9182 | Item_result res_type = | ||
| 9183 | 417 | item_cmp_type(comp_item->result_type(), item->result_type()); | |
| 9184 |
2/6✓ Branch 0 taken 378 times.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
417 | switch (res_type) { |
| 9185 | 378 | case STRING_RESULT: { | |
| 9186 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 376 times.
|
378 | if (item->data_type() == MYSQL_TYPE_JSON) { |
| 9187 | 2 | auto wr = make_unique_destroy_only<Json_wrapper>(thd->mem_root); | |
| 9188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (wr == nullptr) return true; |
| 9189 |
3/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if (item->val_json(wr.get())) return true; |
| 9190 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (item->null_value) |
| 9191 | ✗ | new_item = new Item_null(item->item_name); | |
| 9192 | else | ||
| 9193 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | new_item = new Item_json(std::move(wr), item->item_name); |
| 9194 | 1 | break; | |
| 9195 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | } |
| 9196 | char buff[MAX_FIELD_WIDTH]; | ||
| 9197 | 376 | String tmp(buff, sizeof(buff), &my_charset_bin), *result; | |
| 9198 |
1/2✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
|
376 | result = item->val_str(&tmp); |
| 9199 |
2/4✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 376 times.
|
376 | if (thd->is_error()) return true; |
| 9200 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 375 times.
|
376 | if (item->null_value) |
| 9201 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | new_item = new Item_null(item->item_name); |
| 9202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
|
375 | else if (item->is_temporal()) { |
| 9203 | ✗ | enum_field_types type = item->data_type() == MYSQL_TYPE_TIMESTAMP | |
| 9204 | ✗ | ? MYSQL_TYPE_DATETIME | |
| 9205 | ✗ | : item->data_type(); | |
| 9206 | ✗ | new_item = create_temporal_literal(thd, result->ptr(), result->length(), | |
| 9207 | result->charset(), type, true); | ||
| 9208 | } else { | ||
| 9209 | 375 | size_t length = result->length(); | |
| 9210 |
1/2✓ Branch 0 taken 375 times.
✗ Branch 1 not taken.
|
375 | char *tmp_str = sql_strmake(result->ptr(), length); |
| 9211 |
1/2✓ Branch 0 taken 375 times.
✗ Branch 1 not taken.
|
750 | new_item = new Item_string(item->item_name, tmp_str, length, |
| 9212 |
1/2✓ Branch 0 taken 375 times.
✗ Branch 1 not taken.
|
750 | result->charset()); |
| 9213 | } | ||
| 9214 | 376 | break; | |
| 9215 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
|
376 | } |
| 9216 | 39 | case INT_RESULT: { | |
| 9217 | 39 | longlong result = item->val_int(); | |
| 9218 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | if (thd->is_error()) return true; |
| 9219 | 39 | uint length = item->max_length; | |
| 9220 | 39 | bool null_value = item->null_value; | |
| 9221 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 31 times.
|
39 | if (null_value) |
| 9222 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | new_item = new Item_null(item->item_name); |
| 9223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | else if (item->unsigned_flag) |
| 9224 | ✗ | new_item = new Item_uint(item->item_name, result, length); | |
| 9225 | else | ||
| 9226 |
2/4✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | new_item = new Item_int(item->item_name, result, length); |
| 9227 | 39 | break; | |
| 9228 | } | ||
| 9229 | ✗ | case ROW_RESULT: { | |
| 9230 | /* | ||
| 9231 | Substitute constants only in Item_rows. Don't affect other Items | ||
| 9232 | with ROW_RESULT (eg Item_singlerow_subselect). | ||
| 9233 | |||
| 9234 | For such Items more optimal is to detect if it is constant and replace | ||
| 9235 | it with Item_row. This would optimize queries like this: | ||
| 9236 | SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1); | ||
| 9237 | */ | ||
| 9238 | ✗ | if (!(item->type() == Item::ROW_ITEM && | |
| 9239 | ✗ | comp_item->type() == Item::ROW_ITEM)) | |
| 9240 | ✗ | return false; | |
| 9241 | ✗ | Item_row *item_row = (Item_row *)item; | |
| 9242 | ✗ | Item_row *comp_item_row = (Item_row *)comp_item; | |
| 9243 | /* | ||
| 9244 | If item and comp_item are both Item_rows and have same number of cols | ||
| 9245 | then process items in Item_row one by one. | ||
| 9246 | We can't ignore NULL values here as this item may be used with <=>, in | ||
| 9247 | which case NULL's are significant. | ||
| 9248 | */ | ||
| 9249 | ✗ | assert(item->result_type() == comp_item->result_type()); | |
| 9250 | ✗ | assert(item_row->cols() == comp_item_row->cols()); | |
| 9251 | ✗ | uint col = item_row->cols(); | |
| 9252 | ✗ | while (col-- > 0) | |
| 9253 | ✗ | if (resolve_const_item(thd, item_row->addr(col), | |
| 9254 | ✗ | comp_item_row->element_index(col))) | |
| 9255 | ✗ | return true; | |
| 9256 | ✗ | break; | |
| 9257 | } | ||
| 9258 | ✗ | case REAL_RESULT: { // It must REAL_RESULT | |
| 9259 | ✗ | double result = item->val_real(); | |
| 9260 | ✗ | if (thd->is_error()) return true; | |
| 9261 | ✗ | uint length = item->max_length, decimals = item->decimals; | |
| 9262 | ✗ | bool null_value = item->null_value; | |
| 9263 | ✗ | new_item = (null_value ? (Item *)new Item_null(item->item_name) | |
| 9264 | : (Item *)new Item_float(item->item_name, result, | ||
| 9265 | ✗ | decimals, length)); | |
| 9266 | ✗ | break; | |
| 9267 | } | ||
| 9268 | ✗ | case DECIMAL_RESULT: { | |
| 9269 | ✗ | my_decimal decimal_value; | |
| 9270 | ✗ | my_decimal *result = item->val_decimal(&decimal_value); | |
| 9271 | ✗ | if (thd->is_error()) return true; | |
| 9272 | ✗ | bool null_value = item->null_value; | |
| 9273 | ✗ | new_item = (null_value ? (Item *)new Item_null(item->item_name) | |
| 9274 | : (Item *)new Item_decimal(item->item_name, result, | ||
| 9275 | ✗ | item->decimals, | |
| 9276 | ✗ | item->max_length)); | |
| 9277 | ✗ | break; | |
| 9278 | } | ||
| 9279 | ✗ | default: | |
| 9280 | ✗ | assert(0); | |
| 9281 | } | ||
| 9282 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 416 times.
|
416 | if (new_item == nullptr) return true; |
| 9283 | |||
| 9284 | 416 | *ref = new_item; | |
| 9285 | |||
| 9286 | 416 | return false; | |
| 9287 | } | ||
| 9288 | |||
| 9289 | /** | ||
| 9290 | Compare the value stored in field with the expression from the query. | ||
| 9291 | |||
| 9292 | @param thd Current session. | ||
| 9293 | @param field Field which the Item is stored in after conversion | ||
| 9294 | @param item Original expression from query | ||
| 9295 | |||
| 9296 | @return Returns an integer greater than, equal to, or less than 0 if | ||
| 9297 | the value stored in the field is greater than, equal to, | ||
| 9298 | or less than the original Item. A 0 may also be returned if | ||
| 9299 | out of memory. | ||
| 9300 | |||
| 9301 | @note We use this in the range optimizer/partition pruning, | ||
| 9302 | because in some cases we can't store the value in the field | ||
| 9303 | without some precision/character loss. | ||
| 9304 | |||
| 9305 | We similarly use it to verify that expressions like | ||
| 9306 | BIGINT_FIELD @<cmp@> @<literal value@> | ||
| 9307 | is done correctly (as int/decimal/float according to literal type). | ||
| 9308 | */ | ||
| 9309 | |||
| 9310 | 10220748 | int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) { | |
| 9311 | Item_result res_type = | ||
| 9312 | 10220748 | item_cmp_type(field->result_type(), item->result_type()); | |
| 9313 |
6/6✓ Branch 0 taken 403 times.
✓ Branch 1 taken 10220347 times.
✓ Branch 2 taken 395 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 395 times.
✓ Branch 5 taken 10220355 times.
|
10221153 | if (field->type() == MYSQL_TYPE_TIME && |
| 9314 | 403 | item->data_type() == MYSQL_TYPE_TIME) { | |
| 9315 | 395 | longlong field_value = field->val_time_temporal(); | |
| 9316 | 395 | longlong item_value = item->val_time_temporal(); | |
| 9317 |
2/4✓ Branch 0 taken 395 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 395 times.
|
395 | return field_value < item_value ? -1 : field_value > item_value ? 1 : 0; |
| 9318 | } | ||
| 9319 |
6/6✓ Branch 0 taken 4474 times.
✓ Branch 1 taken 10215880 times.
✓ Branch 2 taken 3256 times.
✓ Branch 3 taken 1218 times.
✓ Branch 4 taken 3256 times.
✓ Branch 5 taken 10217098 times.
|
10220355 | if (is_temporal_type_with_date(field->type()) && item->is_temporal()) { |
| 9320 | /* | ||
| 9321 | Note, in case of TIME data type we also go here | ||
| 9322 | and call item->val_date_temporal(), because we want | ||
| 9323 | TIME to be converted to DATE/DATETIME properly. | ||
| 9324 | Only non-temporal data types go though get_mysql_time_from_str() | ||
| 9325 | in the below code branch. | ||
| 9326 | */ | ||
| 9327 | 3256 | longlong field_value = field->val_date_temporal(); | |
| 9328 | 3256 | longlong item_value = item->val_date_temporal(); | |
| 9329 |
4/4✓ Branch 0 taken 3171 times.
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3169 times.
|
3256 | return field_value < item_value ? -1 : field_value > item_value ? 1 : 0; |
| 9330 | } | ||
| 9331 |
2/2✓ Branch 0 taken 10169111 times.
✓ Branch 1 taken 47987 times.
|
10217098 | if (res_type == STRING_RESULT) { |
| 9332 | char item_buff[MAX_FIELD_WIDTH]; | ||
| 9333 | char field_buff[MAX_FIELD_WIDTH]; | ||
| 9334 | |||
| 9335 | 10169111 | String item_tmp(item_buff, sizeof(item_buff), &my_charset_bin); | |
| 9336 | 10169111 | String field_tmp(field_buff, sizeof(field_buff), &my_charset_bin); | |
| 9337 |
1/2✓ Branch 0 taken 10169111 times.
✗ Branch 1 not taken.
|
10169111 | String *item_result = item->val_str(&item_tmp); |
| 9338 | /* | ||
| 9339 | Some implementations of Item::val_str(String*) actually modify | ||
| 9340 | the field Item::null_value, hence we can't check it earlier. | ||
| 9341 | */ | ||
| 9342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10169111 times.
|
10169111 | if (item->null_value) return 0; |
| 9343 |
1/2✓ Branch 0 taken 10169111 times.
✗ Branch 1 not taken.
|
10169111 | String *field_result = field->val_str(&field_tmp); |
| 9344 | |||
| 9345 |
3/4✓ Branch 0 taken 10169111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1218 times.
✓ Branch 3 taken 10167893 times.
|
10169111 | if (is_temporal_type_with_date(field->type())) { |
| 9346 | enum_mysql_timestamp_type type = | ||
| 9347 |
1/2✓ Branch 0 taken 1218 times.
✗ Branch 1 not taken.
|
1218 | field_type_to_timestamp_type(field->type()); |
| 9348 | 1218 | const char *field_name = field->field_name; | |
| 9349 | MYSQL_TIME field_time, item_time; | ||
| 9350 |
1/2✓ Branch 0 taken 1218 times.
✗ Branch 1 not taken.
|
1218 | get_mysql_time_from_str(thd, field_result, type, field_name, &field_time); |
| 9351 |
1/2✓ Branch 0 taken 1218 times.
✗ Branch 1 not taken.
|
1218 | get_mysql_time_from_str(thd, item_result, type, field_name, &item_time); |
| 9352 | /* | ||
| 9353 | If the string represents a UTC timestamp (with timezone | ||
| 9354 | offset), convert it to a datetime in the current time zone. | ||
| 9355 | */ | ||
| 9356 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1214 times.
|
1218 | if (item_time.time_type == MYSQL_TIMESTAMP_DATETIME_TZ) |
| 9357 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | convert_time_zone_displacement(current_thd->time_zone(), &item_time); |
| 9358 | |||
| 9359 |
2/4✓ Branch 0 taken 1218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1218 times.
✗ Branch 3 not taken.
|
1218 | assert(field_time.time_type != MYSQL_TIMESTAMP_DATETIME_TZ && |
| 9360 | item_time.time_type != MYSQL_TIMESTAMP_DATETIME_TZ); | ||
| 9361 |
1/2✓ Branch 0 taken 1218 times.
✗ Branch 1 not taken.
|
1218 | return my_time_compare(field_time, item_time); |
| 9362 | } | ||
| 9363 |
2/4✓ Branch 0 taken 10167893 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10167893 times.
✗ Branch 3 not taken.
|
10167893 | return sortcmp(field_result, item_result, field->charset()); |
| 9364 | 10169111 | } | |
| 9365 |
2/2✓ Branch 0 taken 44432 times.
✓ Branch 1 taken 3555 times.
|
47987 | if (res_type == INT_RESULT) return 0; // Both are of type int |
| 9366 |
2/2✓ Branch 0 taken 707 times.
✓ Branch 1 taken 2848 times.
|
3555 | if (res_type == DECIMAL_RESULT) { |
| 9367 | 707 | my_decimal item_buf, *item_val, field_buf, *field_val; | |
| 9368 |
1/2✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
|
707 | item_val = item->val_decimal(&item_buf); |
| 9369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 707 times.
|
707 | if (item->null_value) return 0; |
| 9370 |
1/2✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
|
707 | field_val = field->val_decimal(&field_buf); |
| 9371 |
1/2✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
|
707 | return my_decimal_cmp(field_val, item_val); |
| 9372 | 707 | } | |
| 9373 | /* | ||
| 9374 | The patch for Bug#13463415 started using this function for comparing | ||
| 9375 | BIGINTs. That uncovered a bug in Visual Studio 32bit optimized mode. | ||
| 9376 | Prefixing the auto variables with volatile fixes the problem.... | ||
| 9377 | */ | ||
| 9378 | 2848 | volatile double result = item->val_real(); | |
| 9379 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2847 times.
|
2847 | if (item->null_value) return 0; |
| 9380 | 2847 | volatile double field_result = field->val_real(); | |
| 9381 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 2786 times.
|
2848 | if (field_result < result) |
| 9382 | 62 | return -1; | |
| 9383 |
2/2✓ Branch 0 taken 1196 times.
✓ Branch 1 taken 1590 times.
|
2786 | else if (field_result > result) |
| 9384 | 1196 | return 1; | |
| 9385 | 1590 | return 0; | |
| 9386 | } | ||
| 9387 | |||
| 9388 | 345107 | Item_cache *Item_cache::get_cache(const Item *item) { | |
| 9389 | 345107 | return get_cache(item, item->result_type()); | |
| 9390 | } | ||
| 9391 | |||
| 9392 | /** | ||
| 9393 | Get a cache item of given type. | ||
| 9394 | |||
| 9395 | @param item value to be cached | ||
| 9396 | @param type required type of cache | ||
| 9397 | |||
| 9398 | @return cache item | ||
| 9399 | */ | ||
| 9400 | |||
| 9401 | 399131 | Item_cache *Item_cache::get_cache(const Item *item, const Item_result type) { | |
| 9402 |
6/6✓ Branch 0 taken 315833 times.
✓ Branch 1 taken 53351 times.
✓ Branch 2 taken 2561 times.
✓ Branch 3 taken 27231 times.
✓ Branch 4 taken 154 times.
✓ Branch 5 taken 1 times.
|
399131 | switch (type) { |
| 9403 | 315833 | case INT_RESULT: | |
| 9404 | /* | ||
| 9405 | When it's an item of MYSQL_TYPE_BIT, we need to retain its result | ||
| 9406 | as bit format instead of an integer. | ||
| 9407 | */ | ||
| 9408 |
2/2✓ Branch 0 taken 289 times.
✓ Branch 1 taken 315544 times.
|
315833 | if (item->data_type() == MYSQL_TYPE_BIT) |
| 9409 |
2/4✓ Branch 0 taken 289 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 289 times.
✗ Branch 3 not taken.
|
289 | return new Item_cache_bit(item->data_type()); |
| 9410 |
2/4✓ Branch 0 taken 315544 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315544 times.
✗ Branch 3 not taken.
|
315544 | return new Item_cache_int(item->data_type()); |
| 9411 | 53351 | case REAL_RESULT: | |
| 9412 |
1/2✓ Branch 0 taken 53351 times.
✗ Branch 1 not taken.
|
106702 | return new Item_cache_real(); |
| 9413 | 2561 | case DECIMAL_RESULT: | |
| 9414 |
1/2✓ Branch 0 taken 2561 times.
✗ Branch 1 not taken.
|
5122 | return new Item_cache_decimal(); |
| 9415 | 27231 | case STRING_RESULT: | |
| 9416 | /* Not all functions that return DATE/TIME are actually DATE/TIME funcs. | ||
| 9417 | */ | ||
| 9418 |
2/2✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 25719 times.
|
27231 | if (item->is_temporal()) |
| 9419 |
2/4✓ Branch 0 taken 1512 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1512 times.
✗ Branch 3 not taken.
|
1512 | return new Item_cache_datetime(item->data_type()); |
| 9420 |
3/4✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 24111 times.
✓ Branch 2 taken 1608 times.
✗ Branch 3 not taken.
|
27327 | if (item->data_type() == MYSQL_TYPE_JSON) return new Item_cache_json(); |
| 9421 |
2/4✓ Branch 0 taken 24112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24112 times.
✗ Branch 3 not taken.
|
24111 | return new Item_cache_str(item); |
| 9422 | 154 | case ROW_RESULT: | |
| 9423 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
308 | return new Item_cache_row(); |
| 9424 | 1 | default: | |
| 9425 | // should never be in real life | ||
| 9426 | 1 | assert(0); | |
| 9427 | return nullptr; | ||
| 9428 | } | ||
| 9429 | } | ||
| 9430 | |||
| 9431 | 840989 | void Item_cache::store(Item *item) { | |
| 9432 |
2/2✓ Branch 0 taken 691285 times.
✓ Branch 1 taken 149706 times.
|
840989 | if (current_thd->lex->is_exec_started()) |
| 9433 | 691285 | current_thd->change_item_tree(&example, item); | |
| 9434 | else | ||
| 9435 | 149706 | example = item; | |
| 9436 |
2/2✓ Branch 0 taken 42189 times.
✓ Branch 1 taken 798803 times.
|
840992 | if (!item) { |
| 9437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42189 times.
|
42189 | assert(is_nullable()); |
| 9438 | 42189 | null_value = true; | |
| 9439 | } | ||
| 9440 | 840992 | value_cached = false; | |
| 9441 | 840992 | } | |
| 9442 | |||
| 9443 | 2291 | void Item_cache::print(const THD *thd, String *str, | |
| 9444 | enum_query_type query_type) const { | ||
| 9445 | 2291 | str->append(STRING_WITH_LEN("<cache>(")); | |
| 9446 |
1/2✓ Branch 0 taken 2291 times.
✗ Branch 1 not taken.
|
2291 | if (example) |
| 9447 | 2291 | example->print(thd, str, query_type); | |
| 9448 | else | ||
| 9449 | ✗ | Item::print(thd, str, query_type); | |
| 9450 | 2291 | str->append(')'); | |
| 9451 | 2291 | } | |
| 9452 | |||
| 9453 | 4480 | bool Item_cache::walk(Item_processor processor, enum_walk walk, uchar *arg) { | |
| 9454 |
3/4✓ Branch 0 taken 447 times.
✓ Branch 1 taken 704 times.
✓ Branch 2 taken 1151 times.
✗ Branch 3 not taken.
|
5631 | return ((walk & enum_walk::PREFIX) && (this->*processor)(arg)) || |
| 9455 |
7/8✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 3329 times.
✓ Branch 2 taken 4480 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4456 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 3402 times.
✓ Branch 7 taken 1054 times.
|
13489 | (example && example->walk(processor, walk, arg)) || |
| 9456 |
4/4✓ Branch 0 taken 3373 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3388 times.
|
12338 | ((walk & enum_walk::POSTFIX) && (this->*processor)(arg)); |
| 9457 | } | ||
| 9458 | |||
| 9459 | 155895225 | bool Item_cache::has_value() { | |
| 9460 |
6/6✓ Branch 0 taken 197367 times.
✓ Branch 1 taken 155697858 times.
✓ Branch 2 taken 197363 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 155895221 times.
✓ Branch 5 taken 4 times.
|
155895225 | if (value_cached || cache_value()) { |
| 9461 | /* | ||
| 9462 | Only expect NULL if the cache is nullable, or if an error was | ||
| 9463 | raised when reading the value into the cache. | ||
| 9464 | */ | ||
| 9465 |
3/6✓ Branch 0 taken 4920 times.
✓ Branch 1 taken 155890301 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4920 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
155895221 | assert(!null_value || is_nullable() || current_thd->is_error()); |
| 9466 | 155895221 | return !null_value; | |
| 9467 | } | ||
| 9468 | 4 | return false; | |
| 9469 | } | ||
| 9470 | |||
| 9471 | 1419661 | void Item_cache::cleanup() { | |
| 9472 | /* | ||
| 9473 | In case the cache wraps a dynamic parameter, user variable (=> there is an | ||
| 9474 | 'example' item), any next execution should cache the new value. | ||
| 9475 | If no 'example', caching is done through store_value() and that's for | ||
| 9476 | objects which are constant over all executions. | ||
| 9477 | */ | ||
| 9478 |
2/2✓ Branch 0 taken 1373544 times.
✓ Branch 1 taken 46117 times.
|
1419661 | if (example != nullptr) clear(); |
| 9479 | 1419659 | Item::cleanup(); | |
| 9480 | 1419662 | } | |
| 9481 | |||
| 9482 | 76635994 | bool Item_cache_int::cache_value() { | |
| 9483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76635994 times.
|
76635994 | if (!example) return false; |
| 9484 | 76635994 | value_cached = true; | |
| 9485 | 76635994 | value = example->val_int(); | |
| 9486 | 76635996 | null_value = example->null_value; | |
| 9487 | 76635996 | unsigned_flag = example->unsigned_flag; | |
| 9488 | 76635996 | return true; | |
| 9489 | } | ||
| 9490 | |||
| 9491 | ✗ | void Item_cache_int::store_value(Item *item, longlong val_arg) { | |
| 9492 | /* An explicit values is given, save it. */ | ||
| 9493 | ✗ | value_cached = true; | |
| 9494 | ✗ | value = val_arg; | |
| 9495 | ✗ | null_value = item->null_value; | |
| 9496 | ✗ | unsigned_flag = item->unsigned_flag; | |
| 9497 | } | ||
| 9498 | |||
| 9499 | 102 | String *Item_cache_int::val_str(String *str) { | |
| 9500 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
|
102 | assert(fixed == 1); |
| 9501 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 100 times.
|
102 | if (!has_value()) return nullptr; |
| 9502 | 100 | str->set_int(value, unsigned_flag, default_charset()); | |
| 9503 | 100 | return str; | |
| 9504 | } | ||
| 9505 | |||
| 9506 | 2797 | my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) { | |
| 9507 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2797 times.
|
2797 | assert(fixed == 1); |
| 9508 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2797 times.
|
2797 | if (!has_value()) return nullptr; |
| 9509 | 2797 | int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val); | |
| 9510 | 2797 | return decimal_val; | |
| 9511 | } | ||
| 9512 | |||
| 9513 | 1121 | double Item_cache_int::val_real() { | |
| 9514 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1121 times.
|
1121 | assert(fixed == 1); |
| 9515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1121 times.
|
1121 | if (!has_value()) return 0.0; |
| 9516 |
2/2✓ Branch 0 taken 404 times.
✓ Branch 1 taken 717 times.
|
1121 | if (unsigned_flag) return static_cast<unsigned long long>(value); |
| 9517 | 717 | return value; | |
| 9518 | } | ||
| 9519 | |||
| 9520 | 154403381 | longlong Item_cache_int::val_int() { | |
| 9521 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 154403381 times.
|
154403381 | assert(fixed == 1); |
| 9522 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 154403290 times.
|
154403381 | if (!has_value()) return 0; |
| 9523 | 154403290 | return value; | |
| 9524 | } | ||
| 9525 | |||
| 9526 | 6 | String *Item_cache_bit::val_str(String *str) { | |
| 9527 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(fixed); |
| 9528 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (!has_value()) return nullptr; |
| 9529 | |||
| 9530 | char buff[sizeof(longlong)]; | ||
| 9531 | 6 | mi_int8store(buff, value); | |
| 9532 | 6 | uint offset = sizeof(longlong) - string_length(); | |
| 9533 | |||
| 9534 | // for BIT(N), copy last N bits from buff | ||
| 9535 | // (rounded up to an integral number of bytes) | ||
| 9536 | 6 | str->length(0); | |
| 9537 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (str->append(buff + offset, string_length())) return nullptr; |
| 9538 | |||
| 9539 | 6 | return str; | |
| 9540 | } | ||
| 9541 | |||
| 9542 | 5951 | bool Item_cache_datetime::cache_value_int() { | |
| 9543 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5951 times.
|
5951 | if (!example) return false; |
| 9544 | |||
| 9545 | 5951 | value_cached = true; | |
| 9546 | // Mark cached string value obsolete | ||
| 9547 | 5951 | str_value_cached = false; | |
| 9548 | |||
| 9549 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5951 times.
|
5951 | assert(data_type() == example->data_type()); |
| 9550 | 5951 | int_value = example->val_temporal_by_field_type(); | |
| 9551 | 5951 | null_value = example->null_value; | |
| 9552 | 5951 | unsigned_flag = example->unsigned_flag; | |
| 9553 | |||
| 9554 | 5951 | return true; | |
| 9555 | } | ||
| 9556 | |||
| 9557 | 8734 | bool Item_cache_datetime::cache_value() { | |
| 9558 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8734 times.
|
8734 | if (!example) return false; |
| 9559 | |||
| 9560 |
2/2✓ Branch 0 taken 5016 times.
✓ Branch 1 taken 3718 times.
|
8734 | if (cmp_context == INT_RESULT) return cache_value_int(); |
| 9561 | |||
| 9562 | 3718 | str_value_cached = true; | |
| 9563 | // Mark cached int value obsolete | ||
| 9564 | 3718 | value_cached = false; | |
| 9565 | /* Assume here that the underlying item will do correct conversion.*/ | ||
| 9566 | 3718 | String *res = example->val_str(&cached_string); | |
| 9567 |
4/4✓ Branch 0 taken 3080 times.
✓ Branch 1 taken 638 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3067 times.
|
3718 | if (res && res != &cached_string) cached_string.copy(*res); |
| 9568 | 3718 | null_value = example->null_value; | |
| 9569 | 3718 | unsigned_flag = example->unsigned_flag; | |
| 9570 | 3718 | return true; | |
| 9571 | } | ||
| 9572 | |||
| 9573 | 5715 | void Item_cache_datetime::store_value(Item *item, longlong val_arg) { | |
| 9574 | /* An explicit values is given, save it. */ | ||
| 9575 | 5715 | value_cached = true; | |
| 9576 | 5715 | int_value = val_arg; | |
| 9577 | 5715 | null_value = item->null_value; | |
| 9578 | 5715 | unsigned_flag = item->unsigned_flag; | |
| 9579 | 5715 | } | |
| 9580 | |||
| 9581 | 7425 | void Item_cache_datetime::store(Item *item) { | |
| 9582 | 7425 | Item_cache::store(item); | |
| 9583 | 7425 | str_value_cached = false; | |
| 9584 | 7425 | } | |
| 9585 | |||
| 9586 | 5150 | String *Item_cache_datetime::val_str(String *) { | |
| 9587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5150 times.
|
5150 | assert(fixed == 1); |
| 9588 | |||
| 9589 |
4/6✓ Branch 0 taken 3616 times.
✓ Branch 1 taken 1534 times.
✓ Branch 2 taken 3616 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5150 times.
|
5150 | if ((value_cached || str_value_cached) && null_value) return nullptr; |
| 9590 | |||
| 9591 |
2/2✓ Branch 0 taken 1154 times.
✓ Branch 1 taken 3996 times.
|
5150 | if (!str_value_cached) { |
| 9592 | /* | ||
| 9593 | When it's possible the Item_cache_datetime uses INT datetime | ||
| 9594 | representation due to speed reasons. But still, it always has the STRING | ||
| 9595 | result type and thus it can be asked to return a string value. | ||
| 9596 | It is possible that at this time cached item doesn't contain correct | ||
| 9597 | string value, thus we have to convert cached int value to string and | ||
| 9598 | return it. | ||
| 9599 | */ | ||
| 9600 |
1/2✓ Branch 0 taken 1154 times.
✗ Branch 1 not taken.
|
1154 | if (value_cached) { |
| 9601 | MYSQL_TIME ltime; | ||
| 9602 |
1/2✓ Branch 0 taken 1154 times.
✗ Branch 1 not taken.
|
1154 | TIME_from_longlong_packed(<ime, data_type(), int_value); |
| 9603 | 1154 | if ((null_value = | |
| 9604 | 2308 | my_TIME_to_str(<ime, &cached_string, | |
| 9605 |
2/4✓ Branch 0 taken 1154 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1154 times.
|
1154 | min(decimals, uint8{DATETIME_MAX_DECIMALS})))) |
| 9606 | ✗ | return nullptr; | |
| 9607 | 1154 | str_value_cached = true; | |
| 9608 | ✗ | } else if (!cache_value() || null_value) | |
| 9609 | ✗ | return nullptr; | |
| 9610 | } | ||
| 9611 | 5150 | return &cached_string; | |
| 9612 | } | ||
| 9613 | |||
| 9614 | 75 | my_decimal *Item_cache_datetime::val_decimal(my_decimal *decimal_val) { | |
| 9615 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | assert(fixed == 1); |
| 9616 | |||
| 9617 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 71 times.
|
75 | if (str_value_cached) { |
| 9618 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | switch (data_type()) { |
| 9619 | ✗ | case MYSQL_TYPE_TIME: | |
| 9620 | ✗ | return val_decimal_from_time(decimal_val); | |
| 9621 | 4 | case MYSQL_TYPE_DATETIME: | |
| 9622 | case MYSQL_TYPE_TIMESTAMP: | ||
| 9623 | case MYSQL_TYPE_DATE: | ||
| 9624 | 4 | return val_decimal_from_date(decimal_val); | |
| 9625 | ✗ | default: | |
| 9626 | ✗ | assert(0); | |
| 9627 | return nullptr; | ||
| 9628 | } | ||
| 9629 | } | ||
| 9630 | |||
| 9631 |
3/8✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 71 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71 times.
|
71 | if ((!value_cached && !cache_value_int()) || null_value) return nullptr; |
| 9632 | 71 | return my_decimal_from_datetime_packed(decimal_val, data_type(), int_value); | |
| 9633 | } | ||
| 9634 | |||
| 9635 | 1948 | bool Item_cache_datetime::get_date(MYSQL_TIME *ltime, | |
| 9636 | my_time_flags_t fuzzydate) { | ||
| 9637 |
5/6✓ Branch 0 taken 1678 times.
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 1674 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1944 times.
|
1948 | if ((value_cached || str_value_cached) && null_value) return true; |
| 9638 | |||
| 9639 |
2/2✓ Branch 0 taken 1674 times.
✓ Branch 1 taken 274 times.
|
1948 | if (str_value_cached) // TS-TODO: reuse MYSQL_TIME_cache eventually. |
| 9640 | 1674 | return get_date_from_string(ltime, fuzzydate); | |
| 9641 | |||
| 9642 |
5/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 274 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 274 times.
|
274 | if ((!value_cached && !cache_value_int()) || null_value) |
| 9643 | ✗ | return (null_value = true); | |
| 9644 | |||
| 9645 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
|
274 | switch (data_type()) { |
| 9646 | 1 | case MYSQL_TYPE_TIME: { | |
| 9647 | MYSQL_TIME tm; | ||
| 9648 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | TIME_from_longlong_time_packed(&tm, int_value); |
| 9649 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | time_to_datetime(current_thd, &tm, ltime); |
| 9650 | 1 | return false; | |
| 9651 | } | ||
| 9652 | 74 | case MYSQL_TYPE_DATE: { | |
| 9653 | 74 | int warnings = 0; | |
| 9654 |
1/2✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
|
74 | TIME_from_longlong_date_packed(ltime, int_value); |
| 9655 |
1/2✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
|
74 | return check_date(*ltime, non_zero_date(*ltime), fuzzydate, &warnings); |
| 9656 | } | ||
| 9657 | 199 | case MYSQL_TYPE_DATETIME: | |
| 9658 | case MYSQL_TYPE_TIMESTAMP: { | ||
| 9659 | 199 | int warnings = 0; | |
| 9660 |
1/2✓ Branch 0 taken 199 times.
✗ Branch 1 not taken.
|
199 | TIME_from_longlong_datetime_packed(ltime, int_value); |
| 9661 |
1/2✓ Branch 0 taken 199 times.
✗ Branch 1 not taken.
|
199 | return check_date(*ltime, non_zero_date(*ltime), fuzzydate, &warnings); |
| 9662 | } | ||
| 9663 | ✗ | default: | |
| 9664 | ✗ | assert(0); | |
| 9665 | } | ||
| 9666 | return true; | ||
| 9667 | } | ||
| 9668 | |||
| 9669 | 107 | bool Item_cache_datetime::get_time(MYSQL_TIME *ltime) { | |
| 9670 |
4/6✓ Branch 0 taken 20 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 107 times.
|
107 | if ((value_cached || str_value_cached) && null_value) return true; |
| 9671 | |||
| 9672 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 87 times.
|
107 | if (str_value_cached) // TS-TODO: reuse MYSQL_TIME_cache eventually. |
| 9673 | 20 | return get_time_from_string(ltime); | |
| 9674 | |||
| 9675 |
3/8✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 87 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 87 times.
|
87 | if ((!value_cached && !cache_value_int()) || null_value) return true; |
| 9676 | |||
| 9677 |
2/4✓ Branch 0 taken 86 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
87 | switch (data_type()) { |
| 9678 | 86 | case MYSQL_TYPE_TIME: | |
| 9679 | 86 | TIME_from_longlong_time_packed(ltime, int_value); | |
| 9680 | 86 | return false; | |
| 9681 | 1 | case MYSQL_TYPE_DATE: | |
| 9682 | 1 | set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); | |
| 9683 | 1 | return false; | |
| 9684 | ✗ | case MYSQL_TYPE_DATETIME: | |
| 9685 | case MYSQL_TYPE_TIMESTAMP: | ||
| 9686 | ✗ | TIME_from_longlong_datetime_packed(ltime, int_value); | |
| 9687 | ✗ | datetime_to_time(ltime); | |
| 9688 | ✗ | return false; | |
| 9689 | ✗ | default: | |
| 9690 | ✗ | assert(0); | |
| 9691 | } | ||
| 9692 | return true; | ||
| 9693 | } | ||
| 9694 | |||
| 9695 | 15 | double Item_cache_datetime::val_real() { return val_real_from_decimal(); } | |
| 9696 | |||
| 9697 | 739 | longlong Item_cache_datetime::val_time_temporal() { | |
| 9698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 739 times.
|
739 | assert(fixed == 1); |
| 9699 |
7/8✓ Branch 0 taken 16 times.
✓ Branch 1 taken 723 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 731 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 731 times.
|
739 | if ((!value_cached && !cache_value_int()) || null_value) return 0; |
| 9700 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 731 times.
|
731 | if (is_temporal_with_date()) { |
| 9701 | /* Convert packed date to packed time */ | ||
| 9702 | MYSQL_TIME ltime; | ||
| 9703 | ✗ | return get_time_from_date(<ime) | |
| 9704 | ✗ | ? 0 | |
| 9705 | ✗ | : TIME_to_longlong_packed(ltime, data_type()); | |
| 9706 | } | ||
| 9707 | 731 | return int_value; | |
| 9708 | } | ||
| 9709 | |||
| 9710 | 6667 | longlong Item_cache_datetime::val_date_temporal() { | |
| 9711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6667 times.
|
6667 | assert(fixed == 1); |
| 9712 |
7/8✓ Branch 0 taken 915 times.
✓ Branch 1 taken 5752 times.
✓ Branch 2 taken 915 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 6656 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 6656 times.
|
6667 | if ((!value_cached && !cache_value_int()) || null_value) return 0; |
| 9713 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6638 times.
|
6656 | if (data_type() == MYSQL_TYPE_TIME) { |
| 9714 | /* Convert packed time to packed date */ | ||
| 9715 | MYSQL_TIME ltime; | ||
| 9716 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
18 | return get_date_from_time(<ime) ? 0 |
| 9717 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | : TIME_to_longlong_datetime_packed(ltime); |
| 9718 | } | ||
| 9719 | 6638 | return int_value; | |
| 9720 | } | ||
| 9721 | |||
| 9722 | 20 | longlong Item_cache_datetime::val_int() { return val_int_from_decimal(); } | |
| 9723 | |||
| 9724 | 1653 | Item_cache_json::Item_cache_json() | |
| 9725 | : Item_cache(MYSQL_TYPE_JSON), | ||
| 9726 |
1/2✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
|
3306 | m_value(new (*THR_MALLOC) Json_wrapper()), |
| 9727 |
1/2✓ Branch 0 taken 1653 times.
✗ Branch 1 not taken.
|
3306 | m_is_sorted(false) {} |
| 9728 | |||
| 9729 | 6612 | Item_cache_json::~Item_cache_json() { destroy(m_value); } | |
| 9730 | |||
| 9731 | /** | ||
| 9732 | Read the JSON value and cache it. | ||
| 9733 | @return true if the value was successfully cached, false otherwise | ||
| 9734 | */ | ||
| 9735 | 1900 | bool Item_cache_json::cache_value() { | |
| 9736 |
2/4✓ Branch 0 taken 1900 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1900 times.
|
1900 | if (!example || !m_value) return false; |
| 9737 | |||
| 9738 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1889 times.
|
1900 | if (json_value(example, m_value, &value_cached)) { // Error |
| 9739 | 11 | null_value = true; // Set the NULL indicator to prevent reading the value | |
| 9740 | 11 | return false; | |
| 9741 | } | ||
| 9742 | 1889 | null_value = example->null_value; | |
| 9743 | |||
| 9744 |
3/4✓ Branch 0 taken 1889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1653 times.
✓ Branch 3 taken 236 times.
|
1889 | if (value_cached && !null_value) { |
| 9745 | // the row buffer might change, so need own copy | ||
| 9746 | 1653 | m_value->to_dom(); | |
| 9747 | } | ||
| 9748 | 1889 | m_is_sorted = false; | |
| 9749 | 1889 | return value_cached; | |
| 9750 | } | ||
| 9751 | |||
| 9752 | 31 | void Item_cache_json::store_value(Item *expr, Json_wrapper *wr) { | |
| 9753 | 31 | value_cached = true; | |
| 9754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | if ((null_value = expr->null_value)) |
| 9755 | ✗ | m_value = nullptr; | |
| 9756 | else { | ||
| 9757 | 31 | *m_value = *wr; | |
| 9758 | // the row buffer might change, so need own copy | ||
| 9759 | 31 | m_value->to_dom(); | |
| 9760 | } | ||
| 9761 | 31 | m_is_sorted = false; | |
| 9762 | 31 | } | |
| 9763 | |||
| 9764 | /** | ||
| 9765 | Copy the cached JSON value into a wrapper. | ||
| 9766 | @param[out] wr the wrapper that receives the JSON value | ||
| 9767 | */ | ||
| 9768 | 99709 | bool Item_cache_json::val_json(Json_wrapper *wr) { | |
| 9769 |
5/6✓ Branch 0 taken 99701 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 99701 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 99701 times.
✓ Branch 5 taken 8 times.
|
99709 | if (has_value() && !null_value) *wr = *m_value; |
| 9770 | 99709 | return current_thd->is_error(); | |
| 9771 | } | ||
| 9772 | |||
| 9773 | /// Get the name of the cached field of an Item_cache_json instance. | ||
| 9774 | 1290 | inline static const char *whence(const Item_field *cached_field) { | |
| 9775 |
2/2✓ Branch 0 taken 1246 times.
✓ Branch 1 taken 44 times.
|
1290 | return cached_field != nullptr ? cached_field->field_name : "?"; |
| 9776 | } | ||
| 9777 | |||
| 9778 | 821 | String *Item_cache_json::val_str(String *tmp) { | |
| 9779 |
2/2✓ Branch 0 taken 820 times.
✓ Branch 1 taken 1 times.
|
821 | if (has_value()) { |
| 9780 | 820 | tmp->length(0); | |
| 9781 |
1/2✓ Branch 0 taken 820 times.
✗ Branch 1 not taken.
|
820 | m_value->to_string(tmp, true, whence(cached_field), |
| 9782 | JsonDocumentDefaultDepthHandler); | ||
| 9783 | 820 | return tmp; | |
| 9784 | } | ||
| 9785 | |||
| 9786 | 1 | return nullptr; | |
| 9787 | } | ||
| 9788 | |||
| 9789 | 48 | double Item_cache_json::val_real() { | |
| 9790 | 48 | Json_wrapper wr; | |
| 9791 | |||
| 9792 |
2/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
|
48 | if (val_json(&wr)) return 0.0; |
| 9793 | |||
| 9794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (null_value) return 0.0; |
| 9795 | |||
| 9796 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | return wr.coerce_real(whence(cached_field)); |
| 9797 | 48 | } | |
| 9798 | |||
| 9799 | 38 | my_decimal *Item_cache_json::val_decimal(my_decimal *decimal_value) { | |
| 9800 | 38 | Json_wrapper wr; | |
| 9801 | |||
| 9802 |
3/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 37 times.
|
38 | if (val_json(&wr)) return decimal_value; |
| 9803 | |||
| 9804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if (null_value) return decimal_value; |
| 9805 | |||
| 9806 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | return wr.coerce_decimal(decimal_value, whence(cached_field)); |
| 9807 | 38 | } | |
| 9808 | |||
| 9809 | 107 | bool Item_cache_json::get_date(MYSQL_TIME *ltime, my_time_flags_t) { | |
| 9810 | 107 | Json_wrapper wr; | |
| 9811 | |||
| 9812 |
2/4✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107 times.
|
107 | if (val_json(&wr)) return true; |
| 9813 | |||
| 9814 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
|
107 | if (null_value) return true; |
| 9815 | |||
| 9816 |
1/2✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
|
107 | return wr.coerce_date(ltime, whence(cached_field)); |
| 9817 | 107 | } | |
| 9818 | |||
| 9819 | 37 | bool Item_cache_json::get_time(MYSQL_TIME *ltime) { | |
| 9820 | 37 | Json_wrapper wr; | |
| 9821 | |||
| 9822 |
2/4✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
|
37 | if (val_json(&wr)) return true; |
| 9823 | |||
| 9824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if (null_value) return true; |
| 9825 | |||
| 9826 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | return wr.coerce_time(ltime, whence(cached_field)); |
| 9827 | 37 | } | |
| 9828 | |||
| 9829 | 241 | longlong Item_cache_json::val_int() { | |
| 9830 | 241 | Json_wrapper wr; | |
| 9831 |
2/4✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 241 times.
|
241 | if (val_json(&wr)) return 0; |
| 9832 | |||
| 9833 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
|
241 | if (null_value) return true; |
| 9834 | |||
| 9835 |
1/2✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
|
241 | return wr.coerce_int(whence(cached_field)); |
| 9836 | 241 | } | |
| 9837 | |||
| 9838 | 2 | void Item_cache_json::sort() { | |
| 9839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(!m_is_sorted); |
| 9840 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | if (has_value() && m_value->type() == enum_json_type::J_ARRAY) { |
| 9841 | 2 | m_value->sort(); | |
| 9842 | 2 | m_is_sorted = true; | |
| 9843 | } | ||
| 9844 | 2 | } | |
| 9845 | |||
| 9846 | 64859 | bool Item_cache_real::cache_value() { | |
| 9847 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64859 times.
|
64859 | if (!example) return false; |
| 9848 | 64859 | value_cached = true; | |
| 9849 | 64859 | value = example->val_real(); | |
| 9850 | 64859 | null_value = example->null_value; | |
| 9851 | 64859 | return true; | |
| 9852 | } | ||
| 9853 | |||
| 9854 | ✗ | void Item_cache_real::store_value(Item *expr, double d) { | |
| 9855 | ✗ | value_cached = true; | |
| 9856 | ✗ | value = d; | |
| 9857 | ✗ | null_value = expr->null_value; | |
| 9858 | } | ||
| 9859 | |||
| 9860 | 158419 | double Item_cache_real::val_real() { | |
| 9861 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 158419 times.
|
158419 | assert(fixed == 1); |
| 9862 |
2/2✓ Branch 0 taken 4740 times.
✓ Branch 1 taken 153679 times.
|
158419 | if (!has_value()) return 0.0; |
| 9863 | 153679 | return value; | |
| 9864 | } | ||
| 9865 | |||
| 9866 | ✗ | longlong Item_cache_real::val_int() { | |
| 9867 | ✗ | assert(fixed == 1); | |
| 9868 | ✗ | if (!has_value()) return 0; | |
| 9869 | ✗ | return (longlong)rint(value); | |
| 9870 | } | ||
| 9871 | |||
| 9872 | 58 | String *Item_cache_real::val_str(String *str) { | |
| 9873 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | assert(fixed == 1); |
| 9874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (!has_value()) return nullptr; |
| 9875 | 58 | str->set_real(value, decimals, default_charset()); | |
| 9876 | 58 | return str; | |
| 9877 | } | ||
| 9878 | |||
| 9879 | ✗ | my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val) { | |
| 9880 | ✗ | assert(fixed == 1); | |
| 9881 | ✗ | if (!has_value()) return nullptr; | |
| 9882 | ✗ | double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); | |
| 9883 | ✗ | return decimal_val; | |
| 9884 | } | ||
| 9885 | |||
| 9886 | 5212 | bool Item_cache_decimal::cache_value() { | |
| 9887 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5212 times.
|
5212 | if (!example) return false; |
| 9888 | 5212 | value_cached = true; | |
| 9889 | 5212 | my_decimal *val = example->val_decimal(&decimal_value); | |
| 9890 |
6/6✓ Branch 0 taken 5082 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 368 times.
✓ Branch 3 taken 4714 times.
✓ Branch 4 taken 368 times.
✓ Branch 5 taken 4844 times.
|
5212 | if (!(null_value = example->null_value) && val != &decimal_value) |
| 9891 | 368 | my_decimal2decimal(val, &decimal_value); | |
| 9892 | 5212 | return true; | |
| 9893 | } | ||
| 9894 | |||
| 9895 | ✗ | void Item_cache_decimal::store_value(Item *expr, my_decimal *d) { | |
| 9896 | ✗ | value_cached = true; | |
| 9897 | ✗ | null_value = expr->null_value; | |
| 9898 | ✗ | my_decimal cpy(*d); | |
| 9899 | ✗ | decimal_value.swap(cpy); | |
| 9900 | } | ||
| 9901 | |||
| 9902 | 14 | double Item_cache_decimal::val_real() { | |
| 9903 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | assert(fixed); |
| 9904 | double res; | ||
| 9905 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
14 | if (!has_value()) return 0.0; |
| 9906 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); |
| 9907 | 14 | return res; | |
| 9908 | } | ||
| 9909 | |||
| 9910 | ✗ | longlong Item_cache_decimal::val_int() { | |
| 9911 | ✗ | assert(fixed); | |
| 9912 | longlong res; | ||
| 9913 | ✗ | if (!has_value()) return 0; | |
| 9914 | ✗ | my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res); | |
| 9915 | ✗ | return res; | |
| 9916 | } | ||
| 9917 | |||
| 9918 | 288 | String *Item_cache_decimal::val_str(String *str) { | |
| 9919 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
|
288 | assert(fixed); |
| 9920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
|
288 | if (!has_value()) return nullptr; |
| 9921 | 288 | my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, false, | |
| 9922 | &decimal_value); | ||
| 9923 | 288 | my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, str); | |
| 9924 | 288 | return str; | |
| 9925 | } | ||
| 9926 | |||
| 9927 | 253446 | my_decimal *Item_cache_decimal::val_decimal(my_decimal *) { | |
| 9928 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 253446 times.
|
253446 | assert(fixed); |
| 9929 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 253428 times.
|
253446 | if (!has_value()) return nullptr; |
| 9930 | 253428 | return &decimal_value; | |
| 9931 | } | ||
| 9932 | |||
| 9933 | 32449 | bool Item_cache_str::cache_value() { | |
| 9934 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32449 times.
|
32449 | if (!example) return false; |
| 9935 | 32449 | value_cached = true; | |
| 9936 | 32449 | value_buff.set(buffer, sizeof(buffer), example->collation.collation); | |
| 9937 | 32449 | value = example->val_str(&value_buff); | |
| 9938 |
2/2✓ Branch 0 taken 1301 times.
✓ Branch 1 taken 31148 times.
|
32449 | if ((null_value = example->null_value)) |
| 9939 | 1301 | value = nullptr; | |
| 9940 |
5/6✓ Branch 0 taken 31148 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29871 times.
✓ Branch 3 taken 1277 times.
✓ Branch 4 taken 29871 times.
✓ Branch 5 taken 1277 times.
|
31148 | else if (value != nullptr && value->ptr() != buffer) { |
| 9941 | /* | ||
| 9942 | We copy string value to avoid changing value if 'item' is table field | ||
| 9943 | in queries like following (where t1.c is varchar): | ||
| 9944 | select a, | ||
| 9945 | (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'), | ||
| 9946 | (select c from t1 where a=t2.a) | ||
| 9947 | from t2; | ||
| 9948 | */ | ||
| 9949 | 29871 | value_buff.copy(*value); | |
| 9950 | 29871 | value = &value_buff; | |
| 9951 | } | ||
| 9952 | 32449 | return true; | |
| 9953 | } | ||
| 9954 | |||
| 9955 | ✗ | void Item_cache_str::store_value(Item *expr, String &s) { | |
| 9956 | ✗ | value_cached = true; | |
| 9957 | ✗ | if ((null_value = expr->null_value)) | |
| 9958 | ✗ | value = nullptr; | |
| 9959 | else { | ||
| 9960 | ✗ | value_buff.copy(s); | |
| 9961 | ✗ | value = &value_buff; | |
| 9962 | } | ||
| 9963 | } | ||
| 9964 | |||
| 9965 | 65 | double Item_cache_str::val_real() { | |
| 9966 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
|
65 | assert(fixed == 1); |
| 9967 | int err_not_used; | ||
| 9968 | const char *end_not_used; | ||
| 9969 |
2/4✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 65 times.
|
65 | if (!has_value()) return 0.0; |
| 9970 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | if (value) |
| 9971 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | return my_strntod(value->charset(), value->ptr(), value->length(), |
| 9972 | &end_not_used, &err_not_used); | ||
| 9973 | ✗ | return (double)0; | |
| 9974 | } | ||
| 9975 | |||
| 9976 | ✗ | longlong Item_cache_str::val_int() { | |
| 9977 | ✗ | assert(fixed == 1); | |
| 9978 | int err; | ||
| 9979 | ✗ | if (!has_value()) return 0; | |
| 9980 | ✗ | if (value) | |
| 9981 | ✗ | return my_strntoll(value->charset(), value->ptr(), value->length(), 10, | |
| 9982 | nullptr, &err); | ||
| 9983 | else | ||
| 9984 | ✗ | return (longlong)0; | |
| 9985 | } | ||
| 9986 | |||
| 9987 | 974995 | String *Item_cache_str::val_str(String *) { | |
| 9988 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 974995 times.
|
974995 | assert(fixed == 1); |
| 9989 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 974931 times.
|
974995 | if (!has_value()) return nullptr; |
| 9990 | 974931 | return value; | |
| 9991 | } | ||
| 9992 | |||
| 9993 | 1 | my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) { | |
| 9994 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | assert(fixed == 1); |
| 9995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!has_value()) return nullptr; |
| 9996 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (value) |
| 9997 | 1 | str2my_decimal(E_DEC_FATAL_ERROR, value->ptr(), value->length(), | |
| 9998 | 1 | value->charset(), decimal_val); | |
| 9999 | else | ||
| 10000 | ✗ | decimal_val = nullptr; | |
| 10001 | 1 | return decimal_val; | |
| 10002 | } | ||
| 10003 | |||
| 10004 | 650 | type_conversion_status Item_cache_str::save_in_field_inner( | |
| 10005 | Field *field, bool no_conversions) { | ||
| 10006 |
4/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 649 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 650 times.
|
650 | if (!value_cached && !cache_value()) |
| 10007 | ✗ | return TYPE_ERR_BAD_VALUE; // Fatal: couldn't cache the value | |
| 10008 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 649 times.
|
650 | if (null_value) |
| 10009 | 1 | return set_field_to_null_with_conversions(field, no_conversions); | |
| 10010 | const type_conversion_status res = | ||
| 10011 | 649 | Item_cache::save_in_field_inner(field, no_conversions); | |
| 10012 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 649 times.
|
649 | if (is_varbinary && field->type() == MYSQL_TYPE_STRING && value != nullptr && |
| 10013 | ✗ | value->length() < field->field_length) | |
| 10014 | ✗ | return TYPE_WARN_OUT_OF_RANGE; | |
| 10015 | 649 | return res; | |
| 10016 | } | ||
| 10017 | |||
| 10018 | 154 | bool Item_cache_row::allocate(uint num) { | |
| 10019 | 154 | item_count = num; | |
| 10020 | 154 | THD *thd = current_thd; | |
| 10021 | 308 | return (!(values = (Item_cache **)thd->mem_calloc(sizeof(Item_cache *) * | |
| 10022 | 154 | item_count))); | |
| 10023 | } | ||
| 10024 | |||
| 10025 | 302 | bool Item_cache_row::setup(Item *item) { | |
| 10026 | 302 | example = item; | |
| 10027 |
4/6✓ Branch 0 taken 154 times.
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 302 times.
|
302 | if (!values && allocate(item->cols())) return true; |
| 10028 |
2/2✓ Branch 0 taken 638 times.
✓ Branch 1 taken 302 times.
|
940 | for (uint i = 0; i < item_count; i++) { |
| 10029 | 638 | Item *el = item->element_index(i); | |
| 10030 | Item_cache *tmp; | ||
| 10031 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 638 times.
|
638 | if (!(tmp = values[i] = Item_cache::get_cache(el))) return true; |
| 10032 | 638 | tmp->setup(el); | |
| 10033 | 638 | add_accum_properties(tmp); | |
| 10034 | } | ||
| 10035 | 302 | return false; | |
| 10036 | } | ||
| 10037 | |||
| 10038 | 2566 | void Item_cache_row::store(Item *item) { | |
| 10039 | 2566 | example = item; | |
| 10040 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2566 times.
|
2566 | if (!item) { |
| 10041 | ✗ | assert(is_nullable()); | |
| 10042 | ✗ | null_value = true; | |
| 10043 | ✗ | return; | |
| 10044 | } | ||
| 10045 |
2/2✓ Branch 0 taken 5312 times.
✓ Branch 1 taken 2566 times.
|
7878 | for (uint i = 0; i < item_count; i++) |
| 10046 | 5312 | values[i]->store(item->element_index(i)); | |
| 10047 | } | ||
| 10048 | |||
| 10049 | 1263 | bool Item_cache_row::cache_value() { | |
| 10050 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1263 times.
|
1263 | if (!example) return false; |
| 10051 | 1263 | value_cached = true; | |
| 10052 | 1263 | example->bring_value(); | |
| 10053 | 1263 | null_value = example->null_value; | |
| 10054 | |||
| 10055 | const bool cached_item_is_assigned = | ||
| 10056 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1263 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1263 | example->type() != SUBSELECT_ITEM || |
| 10057 | ✗ | down_cast<Item_subselect *>(example)->assigned(); | |
| 10058 | |||
| 10059 |
2/2✓ Branch 0 taken 2616 times.
✓ Branch 1 taken 1263 times.
|
3879 | for (uint i = 0; i < item_count; i++) { |
| 10060 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2616 times.
|
2616 | if (!cached_item_is_assigned) { |
| 10061 | // Subquery with zero rows, so make cached item null also. | ||
| 10062 | ✗ | values[i]->store_null(); | |
| 10063 | } else { | ||
| 10064 | 2616 | values[i]->cache_value(); | |
| 10065 | } | ||
| 10066 | |||
| 10067 | 2616 | null_value |= values[i]->null_value; | |
| 10068 | } | ||
| 10069 | 1263 | return true; | |
| 10070 | } | ||
| 10071 | |||
| 10072 | ✗ | void Item_cache_row::illegal_method_call(const char *method | |
| 10073 | [[maybe_unused]]) const { | ||
| 10074 | ✗ | DBUG_TRACE; | |
| 10075 | ✗ | DBUG_PRINT("error", ("!!! %s method was called for row item", method)); | |
| 10076 | ✗ | assert(0); | |
| 10077 | my_error(ER_OPERAND_COLUMNS, MYF(0), 1); | ||
| 10078 | } | ||
| 10079 | |||
| 10080 | ✗ | bool Item_cache_row::check_cols(uint c) { | |
| 10081 | ✗ | if (c != item_count) { | |
| 10082 | ✗ | my_error(ER_OPERAND_COLUMNS, MYF(0), c); | |
| 10083 | ✗ | return true; | |
| 10084 | } | ||
| 10085 | ✗ | return false; | |
| 10086 | } | ||
| 10087 | |||
| 10088 | ✗ | bool Item_cache_row::null_inside() { | |
| 10089 | ✗ | for (uint i = 0; i < item_count; i++) { | |
| 10090 | ✗ | if (values[i]->cols() > 1) { | |
| 10091 | ✗ | if (values[i]->null_inside()) return true; | |
| 10092 | } else { | ||
| 10093 | ✗ | if (values[i]->update_null_value() || values[i]->null_value) return true; | |
| 10094 | } | ||
| 10095 | } | ||
| 10096 | ✗ | return false; | |
| 10097 | } | ||
| 10098 | |||
| 10099 | 2 | void Item_cache_row::bring_value() { | |
| 10100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!example) return; |
| 10101 | 2 | example->bring_value(); | |
| 10102 | 2 | null_value = example->null_value; | |
| 10103 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | for (uint i = 0; i < item_count; i++) values[i]->bring_value(); |
| 10104 | } | ||
| 10105 | |||
| 10106 | 78904 | Item_aggregate_type::Item_aggregate_type(THD *thd, Item *item) | |
| 10107 | 78904 | : Item(thd, item) { | |
| 10108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78904 times.
|
78904 | assert(item->fixed); |
| 10109 | 78904 | set_nullable(item->is_nullable()); | |
| 10110 |
1/2✓ Branch 0 taken 78904 times.
✗ Branch 1 not taken.
|
78904 | set_data_type(real_data_type(item)); |
| 10111 |
1/2✓ Branch 0 taken 78904 times.
✗ Branch 1 not taken.
|
78904 | set_typelib(item); |
| 10112 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 78821 times.
|
78904 | if (item->data_type() == MYSQL_TYPE_GEOMETRY) |
| 10113 |
1/2✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
|
83 | geometry_type = item->get_geometry_type(); |
| 10114 | else | ||
| 10115 | 78821 | geometry_type = Field::GEOM_GEOMETRY; | |
| 10116 | 78904 | } | |
| 10117 | |||
| 10118 | /** | ||
| 10119 | Return expression type of Item_aggregate_type. | ||
| 10120 | |||
| 10121 | @return | ||
| 10122 | Item_result (type of internal MySQL expression result) | ||
| 10123 | */ | ||
| 10124 | |||
| 10125 | 501625 | Item_result Item_aggregate_type::result_type() const { | |
| 10126 | 501625 | return Field::result_merge_type(data_type()); | |
| 10127 | } | ||
| 10128 | |||
| 10129 | /** | ||
| 10130 | Find real data type of item. | ||
| 10131 | |||
| 10132 | @return | ||
| 10133 | data type which should be used to store item value | ||
| 10134 | */ | ||
| 10135 | |||
| 10136 | 15789121 | static enum_field_types real_data_type(Item *item) { | |
| 10137 | 15789121 | item = item->real_item(); | |
| 10138 | |||
| 10139 |
4/4✓ Branch 0 taken 4737249 times.
✓ Branch 1 taken 14775 times.
✓ Branch 2 taken 5451722 times.
✓ Branch 3 taken 5585375 times.
|
15789121 | switch (item->type()) { |
| 10140 | 4737249 | case Item::FIELD_ITEM: { | |
| 10141 | /* | ||
| 10142 | Item_fields::field_type ask Field_type() but sometimes field return | ||
| 10143 | a different type, like for enum/set, so we need to ask real type. | ||
| 10144 | */ | ||
| 10145 | 4737249 | Field *field = ((Item_field *)item)->field; | |
| 10146 | 4737249 | enum_field_types type = field->real_type(); | |
| 10147 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4737245 times.
|
4737249 | if (field->is_created_from_null_item) return MYSQL_TYPE_NULL; |
| 10148 | /* work around about varchar type field detection */ | ||
| 10149 |
4/6✓ Branch 0 taken 66368 times.
✓ Branch 1 taken 4670877 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66368 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4737245 times.
|
4737245 | if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING) |
| 10150 | ✗ | return MYSQL_TYPE_VAR_STRING; | |
| 10151 | 4737245 | return type; | |
| 10152 | } | ||
| 10153 | 14775 | case Item::SUM_FUNC_ITEM: { | |
| 10154 | /* | ||
| 10155 | Argument of aggregate function sometimes should be asked about field | ||
| 10156 | type | ||
| 10157 | */ | ||
| 10158 | 14775 | Item_sum *item_sum = (Item_sum *)item; | |
| 10159 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 14722 times.
|
14775 | if (item_sum->keep_field_type()) |
| 10160 | 53 | return real_data_type(item_sum->get_arg(0)); | |
| 10161 | 14722 | break; | |
| 10162 | } | ||
| 10163 | 5451722 | case Item::FUNC_ITEM: | |
| 10164 |
2/2✓ Branch 0 taken 7918 times.
✓ Branch 1 taken 5443804 times.
|
5451722 | if (((Item_func *)item)->functype() == Item_func::GUSERVAR_FUNC) { |
| 10165 | /* | ||
| 10166 | There are work around of problem with changing variable type on the | ||
| 10167 | fly and variable always report "string" as field type to get | ||
| 10168 | acceptable information for client in send_field, so we make field | ||
| 10169 | type from expression type. | ||
| 10170 | */ | ||
| 10171 |
3/5✓ Branch 0 taken 7871 times.
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
7918 | switch (item->result_type()) { |
| 10172 | 7871 | case STRING_RESULT: | |
| 10173 | 7871 | return MYSQL_TYPE_VARCHAR; | |
| 10174 | 43 | case INT_RESULT: | |
| 10175 | 43 | return MYSQL_TYPE_LONGLONG; | |
| 10176 | ✗ | case REAL_RESULT: | |
| 10177 | ✗ | return MYSQL_TYPE_DOUBLE; | |
| 10178 | 4 | case DECIMAL_RESULT: | |
| 10179 | 4 | return MYSQL_TYPE_NEWDECIMAL; | |
| 10180 | ✗ | case ROW_RESULT: | |
| 10181 | default: | ||
| 10182 | ✗ | assert(0); | |
| 10183 | return MYSQL_TYPE_VARCHAR; | ||
| 10184 | } | ||
| 10185 | } | ||
| 10186 | 5443804 | break; | |
| 10187 | 5585375 | default: | |
| 10188 | 5585375 | break; | |
| 10189 | } | ||
| 10190 | 11043901 | return item->data_type(); | |
| 10191 | } | ||
| 10192 | |||
| 10193 | /** | ||
| 10194 | Find field type which can carry current Item_aggregate_type type and | ||
| 10195 | type of given Item. | ||
| 10196 | |||
| 10197 | @param thd the thread/connection descriptor | ||
| 10198 | @param item given item to join its parameters with this item ones | ||
| 10199 | |||
| 10200 | @retval | ||
| 10201 | true error - types are incompatible | ||
| 10202 | @retval | ||
| 10203 | false OK | ||
| 10204 | */ | ||
| 10205 | |||
| 10206 | 219169 | bool Item_aggregate_type::join_types(THD *thd, Item *item) { | |
| 10207 |
1/2✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
|
219169 | DBUG_TRACE; |
| 10208 |
6/10✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219169 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 162 times.
✓ Branch 5 taken 219007 times.
✓ Branch 6 taken 162 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 162 times.
✗ Branch 9 not taken.
|
219169 | DBUG_PRINT("info:", |
| 10209 | ("was type %d len %d, dec %d name %s", data_type(), max_length, | ||
| 10210 | decimals, (item_name.is_set() ? item_name.ptr() : "<NULL>"))); | ||
| 10211 |
6/10✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219169 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 162 times.
✓ Branch 5 taken 219007 times.
✓ Branch 6 taken 162 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 162 times.
✗ Branch 9 not taken.
|
219169 | DBUG_PRINT("info:", ("in type %d len %d, dec %d", real_data_type(item), |
| 10212 | item->max_length, item->decimals)); | ||
| 10213 | /* | ||
| 10214 | aggregate_type() will modify the data type of this item. Create a copy of | ||
| 10215 | this item containing the original data type and other properties to ensure | ||
| 10216 | correct conversion from existing item types to aggregated type. | ||
| 10217 | */ | ||
| 10218 |
2/4✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219169 times.
✗ Branch 3 not taken.
|
219169 | Item *item_copy = new Item_metadata_copy(this); |
| 10219 | |||
| 10220 | /* | ||
| 10221 | Down the call stack when calling aggregate_string_properties(), we might | ||
| 10222 | end up in THD::change_item_tree() if we for instance need to convert the | ||
| 10223 | character set on one side of a union: | ||
| 10224 | |||
| 10225 | SELECT "foo" UNION SELECT CONVERT("foo" USING utf8mb3); | ||
| 10226 | might be converted into: | ||
| 10227 | SELECT CONVERT("foo" USING utf8mb3) UNION | ||
| 10228 | SELECT CONVERT("foo" USING utf8mb3); | ||
| 10229 | |||
| 10230 | If we are in a prepared statement or a stored routine (any non-conventional | ||
| 10231 | query that needs rollback of any item tree modifications), we need to | ||
| 10232 | remember what Item we changed ("foo" in this case) and where that Item is | ||
| 10233 | located (in the "args" array in this case) so we can roll back the changes | ||
| 10234 | done to the Item tree when the execution is done. When we enter the rollback | ||
| 10235 | code (THD::rollback_item_tree_changes()), the location of the Item need to | ||
| 10236 | be accessible, so that is why the "args" array must be allocated on a | ||
| 10237 | MEM_ROOT and not on the stack. Note that THD::change_item_tree() isn't | ||
| 10238 | necessary, since the Item array we are modifying isn't a part of the | ||
| 10239 | original Item tree. | ||
| 10240 | */ | ||
| 10241 |
1/2✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
|
219169 | Item **args = new (thd->mem_root) Item *[2] { item_copy, item }; |
| 10242 |
2/4✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219169 times.
✗ Branch 3 not taken.
|
219169 | aggregate_type(make_array(&args[0], 2)); |
| 10243 | |||
| 10244 |
1/2✓ Branch 0 taken 219169 times.
✗ Branch 1 not taken.
|
219169 | Item_result merge_type = Field::result_merge_type(data_type()); |
| 10245 |
2/2✓ Branch 0 taken 201649 times.
✓ Branch 1 taken 17520 times.
|
219169 | if (merge_type == STRING_RESULT) { |
| 10246 |
3/4✓ Branch 0 taken 201649 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 201646 times.
|
201649 | if (aggregate_string_properties("UNION", args, 2)) return true; |
| 10247 | /* | ||
| 10248 | For geometry columns, we must also merge subtypes. If the | ||
| 10249 | subtypes are different, use GEOMETRY. | ||
| 10250 | */ | ||
| 10251 |
6/6✓ Branch 0 taken 90 times.
✓ Branch 1 taken 201556 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 62 times.
✓ Branch 5 taken 201584 times.
|
201825 | if (data_type() == MYSQL_TYPE_GEOMETRY && |
| 10252 | 90 | (item->data_type() != MYSQL_TYPE_GEOMETRY || | |
| 10253 |
3/4✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 28 times.
|
89 | geometry_type != item->get_geometry_type())) |
| 10254 | 62 | geometry_type = Field::GEOM_GEOMETRY; | |
| 10255 | } else | ||
| 10256 |
1/2✓ Branch 0 taken 17520 times.
✗ Branch 1 not taken.
|
17520 | aggregate_num_type(merge_type, args, 2); |
| 10257 |
4/4✓ Branch 0 taken 95121 times.
✓ Branch 1 taken 124045 times.
✓ Branch 2 taken 2156 times.
✓ Branch 3 taken 92965 times.
|
219166 | set_nullable(is_nullable() || item->is_nullable()); |
| 10258 |
1/2✓ Branch 0 taken 219166 times.
✗ Branch 1 not taken.
|
219166 | set_typelib(item); |
| 10259 |
5/8✓ Branch 0 taken 219166 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219166 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 162 times.
✓ Branch 5 taken 219004 times.
✓ Branch 6 taken 162 times.
✗ Branch 7 not taken.
|
219166 | DBUG_PRINT("info", ("become type: %d len: %u dec: %u", (int)data_type(), |
| 10260 | max_length, (uint)decimals)); | ||
| 10261 | 219166 | return false; | |
| 10262 | 219169 | } | |
| 10263 | |||
| 10264 | /** | ||
| 10265 | Calculate length for merging result for given Item type. | ||
| 10266 | |||
| 10267 | @param item Item for length detection | ||
| 10268 | |||
| 10269 | @return | ||
| 10270 | length | ||
| 10271 | */ | ||
| 10272 | |||
| 10273 | ✗ | uint32 Item_aggregate_type::display_length(Item *item) { | |
| 10274 | ✗ | if (item->type() == Item::FIELD_ITEM) | |
| 10275 | ✗ | return ((Item_field *)item)->max_disp_length(); | |
| 10276 | |||
| 10277 | ✗ | switch (item->data_type()) { | |
| 10278 | ✗ | case MYSQL_TYPE_DECIMAL: | |
| 10279 | case MYSQL_TYPE_TIMESTAMP: | ||
| 10280 | case MYSQL_TYPE_DATE: | ||
| 10281 | case MYSQL_TYPE_TIME: | ||
| 10282 | case MYSQL_TYPE_DATETIME: | ||
| 10283 | case MYSQL_TYPE_YEAR: | ||
| 10284 | case MYSQL_TYPE_NEWDATE: | ||
| 10285 | case MYSQL_TYPE_VARCHAR: | ||
| 10286 | case MYSQL_TYPE_BIT: | ||
| 10287 | case MYSQL_TYPE_NEWDECIMAL: | ||
| 10288 | case MYSQL_TYPE_ENUM: | ||
| 10289 | case MYSQL_TYPE_SET: | ||
| 10290 | case MYSQL_TYPE_TINY_BLOB: | ||
| 10291 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 10292 | case MYSQL_TYPE_LONG_BLOB: | ||
| 10293 | case MYSQL_TYPE_BLOB: | ||
| 10294 | case MYSQL_TYPE_VAR_STRING: | ||
| 10295 | case MYSQL_TYPE_STRING: | ||
| 10296 | case MYSQL_TYPE_GEOMETRY: | ||
| 10297 | case MYSQL_TYPE_JSON: | ||
| 10298 | ✗ | return item->max_length; | |
| 10299 | ✗ | case MYSQL_TYPE_BOOL: | |
| 10300 | ✗ | return 5; | |
| 10301 | ✗ | case MYSQL_TYPE_TINY: | |
| 10302 | ✗ | return 4; | |
| 10303 | ✗ | case MYSQL_TYPE_SHORT: | |
| 10304 | ✗ | return 6; | |
| 10305 | ✗ | case MYSQL_TYPE_LONG: | |
| 10306 | ✗ | return MY_INT32_NUM_DECIMAL_DIGITS; | |
| 10307 | ✗ | case MYSQL_TYPE_FLOAT: | |
| 10308 | ✗ | return 25; | |
| 10309 | ✗ | case MYSQL_TYPE_DOUBLE: | |
| 10310 | ✗ | return 53; | |
| 10311 | ✗ | case MYSQL_TYPE_NULL: | |
| 10312 | ✗ | return 0; | |
| 10313 | ✗ | case MYSQL_TYPE_LONGLONG: | |
| 10314 | ✗ | return 20; | |
| 10315 | ✗ | case MYSQL_TYPE_INT24: | |
| 10316 | ✗ | return 8; | |
| 10317 | ✗ | case MYSQL_TYPE_INVALID: | |
| 10318 | default: | ||
| 10319 | ✗ | assert(0); // we should never go there | |
| 10320 | return 0; | ||
| 10321 | } | ||
| 10322 | } | ||
| 10323 | |||
| 10324 | /** | ||
| 10325 | Make temporary table field according collected information about type | ||
| 10326 | of UNION result. | ||
| 10327 | |||
| 10328 | @param table temporary table for which we create fields | ||
| 10329 | @param strict If strict mode is on | ||
| 10330 | |||
| 10331 | @return | ||
| 10332 | created field | ||
| 10333 | */ | ||
| 10334 | |||
| 10335 | 153265 | Field *Item_aggregate_type::make_field_by_type(TABLE *table, bool strict) { | |
| 10336 | /* | ||
| 10337 | The field functions defines a field to be not null if null_ptr is not 0 | ||
| 10338 | */ | ||
| 10339 | Field *field; | ||
| 10340 | |||
| 10341 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 153253 times.
|
153265 | switch (data_type()) { |
| 10342 | 4 | case MYSQL_TYPE_ENUM: | |
| 10343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(m_typelib != nullptr); |
| 10344 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
12 | field = new (*THR_MALLOC) |
| 10345 | 4 | Field_enum(max_length, is_nullable(), item_name.ptr(), | |
| 10346 | 4 | get_enum_pack_length(m_typelib->count), m_typelib, | |
| 10347 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | collation.collation); |
| 10348 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (field) field->init(table); |
| 10349 | 4 | break; | |
| 10350 | ✗ | case MYSQL_TYPE_SET: | |
| 10351 | ✗ | assert(m_typelib != nullptr); | |
| 10352 | ✗ | field = new (*THR_MALLOC) | |
| 10353 | ✗ | Field_set(max_length, is_nullable(), item_name.ptr(), | |
| 10354 | ✗ | get_set_pack_length(m_typelib->count), m_typelib, | |
| 10355 | ✗ | collation.collation); | |
| 10356 | ✗ | if (field) field->init(table); | |
| 10357 | ✗ | break; | |
| 10358 | 8 | case MYSQL_TYPE_NULL: | |
| 10359 | 8 | field = make_string_field(table); | |
| 10360 | 8 | break; | |
| 10361 | 153253 | default: | |
| 10362 | 153253 | field = tmp_table_field_from_field_type(table, false); | |
| 10363 | 153253 | break; | |
| 10364 | } | ||
| 10365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 153265 times.
|
153265 | if (field == nullptr) return nullptr; |
| 10366 | |||
| 10367 |
6/6✓ Branch 0 taken 62741 times.
✓ Branch 1 taken 90524 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 62702 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 153247 times.
|
153304 | if (strict && is_temporal_type_with_date(field->type()) && |
| 10368 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 21 times.
|
39 | !field->is_nullable()) { |
| 10369 | /* | ||
| 10370 | This function is used for CREATE SELECT UNION [ALL] ... , and, if | ||
| 10371 | expression is non-nullable, the resulting column is declared | ||
| 10372 | non-nullable with a default of 0. However, in strict mode, for dates, | ||
| 10373 | 0000-00-00 is invalid; in that case, don't give any default. | ||
| 10374 | */ | ||
| 10375 | 18 | field->set_flag(NO_DEFAULT_VALUE_FLAG); | |
| 10376 | } | ||
| 10377 | 153265 | field->set_derivation(collation.derivation); | |
| 10378 | 153265 | return field; | |
| 10379 | } | ||
| 10380 | |||
| 10381 | /** | ||
| 10382 | Set typelib information for an aggregated enum/set field. | ||
| 10383 | Aggregation of typelib information is possible only if there is a single | ||
| 10384 | underlying item with type enum/set, all other items must be the NULL value. | ||
| 10385 | Aggregation is performed by calling this function repeatedly for each | ||
| 10386 | underlying item. | ||
| 10387 | |||
| 10388 | @param item Item for information collection | ||
| 10389 | */ | ||
| 10390 | 298070 | void Item_aggregate_type::set_typelib(Item *item) { | |
| 10391 |
6/6✓ Branch 0 taken 297476 times.
✓ Branch 1 taken 594 times.
✓ Branch 2 taken 297471 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 297471 times.
✓ Branch 5 taken 599 times.
|
298070 | if (data_type() != MYSQL_TYPE_ENUM && data_type() != MYSQL_TYPE_SET) return; |
| 10392 | |||
| 10393 | // Check that only one underlying item is not the NULL value | ||
| 10394 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 598 times.
|
599 | if (m_typelib != nullptr) { |
| 10395 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | assert(real_data_type(item) == MYSQL_TYPE_NULL); |
| 10396 | } else { | ||
| 10397 |
3/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
|
598 | assert(real_data_type(item) == MYSQL_TYPE_ENUM || |
| 10398 | real_data_type(item) == MYSQL_TYPE_SET); | ||
| 10399 | 598 | m_typelib = item->get_typelib(); | |
| 10400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(m_typelib != nullptr); |
| 10401 | } | ||
| 10402 | } | ||
| 10403 | |||
| 10404 | ✗ | double Item_type_holder::val_real() { | |
| 10405 | ✗ | assert(0); // should never be called | |
| 10406 | return 0.0; | ||
| 10407 | } | ||
| 10408 | |||
| 10409 | ✗ | longlong Item_type_holder::val_int() { | |
| 10410 | ✗ | assert(0); // should never be called | |
| 10411 | return 0; | ||
| 10412 | } | ||
| 10413 | |||
| 10414 | ✗ | my_decimal *Item_type_holder::val_decimal(my_decimal *) { | |
| 10415 | ✗ | assert(0); // should never be called | |
| 10416 | return nullptr; | ||
| 10417 | } | ||
| 10418 | |||
| 10419 | ✗ | String *Item_type_holder::val_str(String *) { | |
| 10420 | ✗ | assert(0); // should never be called | |
| 10421 | return nullptr; | ||
| 10422 | } | ||
| 10423 | |||
| 10424 | ✗ | bool Item_type_holder::get_date(MYSQL_TIME *, my_time_flags_t) { | |
| 10425 | ✗ | assert(0); | |
| 10426 | return true; | ||
| 10427 | } | ||
| 10428 | |||
| 10429 | ✗ | bool Item_type_holder::get_time(MYSQL_TIME *) { | |
| 10430 | ✗ | assert(0); | |
| 10431 | return true; | ||
| 10432 | } | ||
| 10433 | |||
| 10434 | 136 | type_conversion_status Item_values_column::save_in_field_inner( | |
| 10435 | Field *to, bool no_conversions) { | ||
| 10436 | type_conversion_status res; | ||
| 10437 | 136 | res = m_value_ref->save_in_field(to, no_conversions); | |
| 10438 | 136 | null_value = m_value_ref->null_value; | |
| 10439 | 136 | return res; | |
| 10440 | } | ||
| 10441 | |||
| 10442 | 158 | Item_values_column::Item_values_column(THD *thd, Item *ref) : super(thd, ref) { | |
| 10443 | 158 | fixed = true; | |
| 10444 | 158 | } | |
| 10445 | |||
| 10446 | /* purecov: begin deadcode */ | ||
| 10447 | |||
| 10448 | ✗ | bool Item_values_column::eq(const Item *item, bool binary_cmp) const { | |
| 10449 | ✗ | assert(false); | |
| 10450 | const Item *it = item->real_item(); | ||
| 10451 | return m_value_ref && m_value_ref->eq(it, binary_cmp); | ||
| 10452 | } | ||
| 10453 | |||
| 10454 | /* purecov: end */ | ||
| 10455 | |||
| 10456 | 2 | double Item_values_column::val_real() { | |
| 10457 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(fixed); |
| 10458 | 2 | double tmp = m_value_ref->val_real(); | |
| 10459 | 2 | null_value = m_value_ref->null_value; | |
| 10460 | 2 | return tmp; | |
| 10461 | } | ||
| 10462 | |||
| 10463 | 163 | longlong Item_values_column::val_int() { | |
| 10464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
|
163 | assert(fixed); |
| 10465 | 163 | longlong tmp = m_value_ref->val_int(); | |
| 10466 | 163 | null_value = m_value_ref->null_value; | |
| 10467 | 163 | return tmp; | |
| 10468 | } | ||
| 10469 | |||
| 10470 | /* purecov: begin deadcode */ | ||
| 10471 | |||
| 10472 | ✗ | my_decimal *Item_values_column::val_decimal(my_decimal *decimal_value) { | |
| 10473 | ✗ | assert(false); | |
| 10474 | assert(fixed); | ||
| 10475 | my_decimal *val = m_value_ref->val_decimal(decimal_value); | ||
| 10476 | null_value = m_value_ref->null_value; | ||
| 10477 | return val; | ||
| 10478 | } | ||
| 10479 | |||
| 10480 | ✗ | bool Item_values_column::val_bool() { | |
| 10481 | ✗ | assert(false); | |
| 10482 | assert(fixed); | ||
| 10483 | bool tmp = m_value_ref->val_bool(); | ||
| 10484 | null_value = m_value_ref->null_value; | ||
| 10485 | return tmp; | ||
| 10486 | } | ||
| 10487 | |||
| 10488 | ✗ | bool Item_values_column::val_json(Json_wrapper *result) { | |
| 10489 | ✗ | assert(false); | |
| 10490 | assert(fixed); | ||
| 10491 | bool ok = m_value_ref->val_json(result); | ||
| 10492 | null_value = m_value_ref->null_value; | ||
| 10493 | return ok; | ||
| 10494 | } | ||
| 10495 | |||
| 10496 | /* purecov: end */ | ||
| 10497 | |||
| 10498 | 8 | String *Item_values_column::val_str(String *tmp) { | |
| 10499 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | assert(fixed); |
| 10500 | 8 | tmp = m_value_ref->val_str(tmp); | |
| 10501 | 8 | null_value = m_value_ref->null_value; | |
| 10502 | 8 | return tmp; | |
| 10503 | } | ||
| 10504 | |||
| 10505 | 10 | bool Item_values_column::is_null() { | |
| 10506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | assert(fixed); |
| 10507 | /* | ||
| 10508 | Item_values_column is dualistic in nature: It represents both a set | ||
| 10509 | of values, and, during evaluation, an individual value in this set. | ||
| 10510 | This assert will ensure that we only check nullability of individual | ||
| 10511 | values, since a set of values is never NULL. Note that setting | ||
| 10512 | RAND_TABLE_BIT in the constructor prevents this function from being called | ||
| 10513 | during resolving. | ||
| 10514 | */ | ||
| 10515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | assert(m_value_ref != nullptr); |
| 10516 | 10 | bool tmp = m_value_ref->is_null(); | |
| 10517 | 10 | null_value = m_value_ref->null_value; | |
| 10518 | 10 | return tmp; | |
| 10519 | } | ||
| 10520 | |||
| 10521 | 4 | bool Item_values_column::get_date(MYSQL_TIME *ltime, | |
| 10522 | my_time_flags_t fuzzydate) { | ||
| 10523 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(fixed); |
| 10524 | 4 | bool result = m_value_ref->get_date(ltime, fuzzydate); | |
| 10525 | 4 | null_value = m_value_ref->null_value; | |
| 10526 | 4 | return result; | |
| 10527 | } | ||
| 10528 | |||
| 10529 | 2 | bool Item_values_column::get_time(MYSQL_TIME *ltime) { | |
| 10530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(fixed); |
| 10531 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(m_value_ref != nullptr); |
| 10532 | 2 | return m_value_ref->get_time(ltime); | |
| 10533 | } | ||
| 10534 | |||
| 10535 | 340 | void Item_values_column::add_used_tables(Item *value) { | |
| 10536 | 340 | m_aggregated_used_tables |= value->used_tables(); | |
| 10537 | 340 | } | |
| 10538 | |||
| 10539 | 96978587 | void Item_result_field::cleanup() { | |
| 10540 |
1/2✓ Branch 0 taken 96989454 times.
✗ Branch 1 not taken.
|
96978587 | DBUG_TRACE; |
| 10541 | 96989454 | Item::cleanup(); | |
| 10542 | 96988496 | result_field = nullptr; | |
| 10543 | 96988496 | } | |
| 10544 | |||
| 10545 | 283 | void Item_result_field::raise_numeric_overflow(const char *type_name) { | |
| 10546 | char buf[256]; | ||
| 10547 | 283 | String str(buf, sizeof(buf), system_charset_info); | |
| 10548 | 283 | str.length(0); | |
| 10549 |
2/4✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
|
283 | print(current_thd, &str, QT_NO_DATA_EXPANSION); |
| 10550 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | str.append('\0'); |
| 10551 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.ptr()); |
| 10552 | 283 | } | |
| 10553 | |||
| 10554 | /** | ||
| 10555 | Helper method: Convert string to the given charset, then print. | ||
| 10556 | |||
| 10557 | @param from_str String to be converted. | ||
| 10558 | @param to_str Query string. | ||
| 10559 | @param to_cs Character set to which the string is to be converted. | ||
| 10560 | */ | ||
| 10561 | 1404843 | void convert_and_print(const String *from_str, String *to_str, | |
| 10562 | const CHARSET_INFO *to_cs) { | ||
| 10563 |
2/2✓ Branch 0 taken 884813 times.
✓ Branch 1 taken 520030 times.
|
1404843 | if (my_charset_same(from_str->charset(), to_cs)) { |
| 10564 | 884813 | from_str->print(to_str); // already in to_cs, no need to convert | |
| 10565 | } else // need to convert | ||
| 10566 | { | ||
| 10567 |
1/2✓ Branch 0 taken 520030 times.
✗ Branch 1 not taken.
|
520030 | THD *thd = current_thd; |
| 10568 | LEX_STRING lex_str; | ||
| 10569 |
1/2✓ Branch 0 taken 520030 times.
✗ Branch 1 not taken.
|
520030 | thd->convert_string(&lex_str, to_cs, from_str->ptr(), from_str->length(), |
| 10570 | from_str->charset()); | ||
| 10571 | 520030 | String tmp(lex_str.str, lex_str.length, to_cs); | |
| 10572 |
1/2✓ Branch 0 taken 520030 times.
✗ Branch 1 not taken.
|
520030 | tmp.print(to_str); |
| 10573 | 520030 | } | |
| 10574 | 1404843 | } | |
| 10575 | |||
| 10576 | /** | ||
| 10577 | Tells if this is a column of a table whose qualifying query block is 'sl'. | ||
| 10578 | I.e. Item_field or Item_view_ref resolved in 'sl'. Used for | ||
| 10579 | aggregate checks. | ||
| 10580 | |||
| 10581 | @note This returns false for an alias to a SELECT list expression, | ||
| 10582 | even though the SELECT list expression might itself be a column of the | ||
| 10583 | @<table expression@>; i.e. when the function runs on "foo" in HAVING of | ||
| 10584 | "select t1.a as foo from t1 having foo @> 1", it returns false. First, it | ||
| 10585 | pedantically makes sense: "foo" in HAVING is a reference to a column of the | ||
| 10586 | @<query expression@>, not of the @<table expression@>. Second, this behaviour | ||
| 10587 | makes sense for our purpose: | ||
| 10588 | - This is an alias to a SELECT list expression. | ||
| 10589 | - If doing DISTINCT-related checks, this alias can be ignored. | ||
| 10590 | - If doing GROUP-BY-related checks, the aliased expression was already | ||
| 10591 | checked when we checked the SELECT list, so can be ignored. | ||
| 10592 | |||
| 10593 | @retval true3 yes | ||
| 10594 | @retval false3 no | ||
| 10595 | @retval unknown3 it's a non-direct-view Item_ref, we don't know if it | ||
| 10596 | contains a column => caller please analyze "*ref" | ||
| 10597 | */ | ||
| 10598 | 244919 | Bool3 Item_ident::local_column(const Query_block *sl) const | |
| 10599 | |||
| 10600 | { | ||
| 10601 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 244919 times.
|
244919 | assert(fixed); |
| 10602 |
2/2✓ Branch 0 taken 367 times.
✓ Branch 1 taken 244552 times.
|
244919 | if (m_alias_of_expr) return Bool3::false3(); |
| 10603 | 244552 | const Type t = type(); | |
| 10604 |
5/6✓ Branch 0 taken 234072 times.
✓ Branch 1 taken 10480 times.
✓ Branch 2 taken 234072 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11716 times.
✓ Branch 5 taken 232836 times.
|
478624 | if (t == FIELD_ITEM || |
| 10605 | 234072 | (t == REF_ITEM && | |
| 10606 |
2/2✓ Branch 0 taken 1236 times.
✓ Branch 1 taken 232836 times.
|
234072 | static_cast<const Item_ref *>(this)->ref_type() == Item_ref::VIEW_REF)) { |
| 10607 |
2/2✓ Branch 0 taken 140 times.
✓ Branch 1 taken 11576 times.
|
11716 | if (depended_from) // outer reference |
| 10608 | { | ||
| 10609 |
2/2✓ Branch 0 taken 110 times.
✓ Branch 1 taken 30 times.
|
140 | if (depended_from == sl) |
| 10610 | 110 | return Bool3::true3(); // qualifying query is 'sl' | |
| 10611 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 11534 times.
|
11576 | } else if (context == nullptr) { |
| 10612 | /* | ||
| 10613 | Must be an underlying column of a generated column | ||
| 10614 | as we've dove so deep, we know the gcol is local to 'sl', and so is | ||
| 10615 | this column. | ||
| 10616 | */ | ||
| 10617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | assert(t == FIELD_ITEM); |
| 10618 | 42 | return Bool3::true3(); | |
| 10619 |
2/2✓ Branch 0 taken 11294 times.
✓ Branch 1 taken 240 times.
|
11534 | } else if (context->query_block == sl) |
| 10620 | 11294 | return Bool3::true3(); // qualifying query is 'sl' | |
| 10621 |
1/2✓ Branch 0 taken 232836 times.
✗ Branch 1 not taken.
|
232836 | } else if (t == REF_ITEM) { |
| 10622 | /* | ||
| 10623 | We also know that this is not an alias. Must be an internal Item_ref | ||
| 10624 | (like Item_aggregate_ref, Item_outer_ref), go down into it: | ||
| 10625 | */ | ||
| 10626 | 232836 | return Bool3::unknown3(); | |
| 10627 | } | ||
| 10628 | 270 | return Bool3::false3(); | |
| 10629 | } | ||
| 10630 | |||
| 10631 | 270 | bool Item_ident::aggregate_check_distinct(uchar *arg) { | |
| 10632 | 270 | Distinct_check *const dc = reinterpret_cast<Distinct_check *>(arg); | |
| 10633 | |||
| 10634 |
2/2✓ Branch 0 taken 162 times.
✓ Branch 1 taken 108 times.
|
270 | if (dc->is_stopped(this)) return false; |
| 10635 | |||
| 10636 | 108 | Query_block *const sl = dc->select; | |
| 10637 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | const Bool3 local = local_column(sl); |
| 10638 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 96 times.
|
108 | if (local.is_false()) { |
| 10639 | // not a column => ignored, skip child. Other tree parts deserve checking. | ||
| 10640 | 12 | dc->stop_at(this); | |
| 10641 | 12 | return false; | |
| 10642 | } | ||
| 10643 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 84 times.
|
96 | if (local.is_unknown()) return false; // dive in child item |
| 10644 | |||
| 10645 | /* | ||
| 10646 | Point (2) of Distinct_check::check_query() is true: column is | ||
| 10647 | from table whose qualifying query block is 'sl'. | ||
| 10648 | */ | ||
| 10649 | uint counter; | ||
| 10650 | enum_resolution_type resolution; | ||
| 10651 |
2/4✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
84 | Item **const res = find_item_in_list(current_thd, this, &sl->fields, &counter, |
| 10652 | REPORT_EXCEPT_NOT_FOUND, &resolution); | ||
| 10653 | |||
| 10654 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 24 times.
|
84 | if (res == not_found_item) { |
| 10655 | /* | ||
| 10656 | Point (3) of Distinct_check::check_query() is true: column is | ||
| 10657 | not in SELECT list. | ||
| 10658 | */ | ||
| 10659 | 60 | dc->failed_ident = this; | |
| 10660 | // Abort processing of the entire item tree. | ||
| 10661 | 60 | return true; | |
| 10662 | } | ||
| 10663 | /* | ||
| 10664 | If success, do not dive in the child either! Indeed if this is | ||
| 10665 | Item_.*view_ref to an expression coming from a merged view, we mustn't | ||
| 10666 | check its underlying base-table columns, it may give false errors, | ||
| 10667 | consider: | ||
| 10668 | create view v as select x*2 as b from ...; | ||
| 10669 | select distinct b from v order by b+1; | ||
| 10670 | 'b' of ORDER BY is in SELECT list so query is valid, we mustn't check | ||
| 10671 | the underlying 'x' (which is not in SELECT list). | ||
| 10672 | */ | ||
| 10673 | 24 | dc->stop_at(this); | |
| 10674 | 24 | return false; | |
| 10675 | } | ||
| 10676 | |||
| 10677 | 596373 | bool Item_ident::aggregate_check_group(uchar *arg) { | |
| 10678 | 596373 | Group_check *const gc = reinterpret_cast<Group_check *>(arg); | |
| 10679 | 596373 | return gc->do_ident_check(this, 0, Group_check::CHECK_GROUP); | |
| 10680 | } | ||
| 10681 | |||
| 10682 | 270 | bool Item_ident::is_strong_side_column_not_in_fd(uchar *arg) { | |
| 10683 | 270 | std::pair<Group_check *, table_map> *p = | |
| 10684 | reinterpret_cast<std::pair<Group_check *, table_map> *>(arg); | ||
| 10685 | // p->first is Group_check, p->second is map of strong tables. | ||
| 10686 | 270 | return p->first->do_ident_check(this, p->second, | |
| 10687 | 270 | Group_check::CHECK_STRONG_SIDE_COLUMN); | |
| 10688 | } | ||
| 10689 | |||
| 10690 | 78 | bool Item_ident::is_column_not_in_fd(uchar *arg) { | |
| 10691 | 78 | Group_check *const gc = reinterpret_cast<Group_check *>(arg); | |
| 10692 | 78 | return gc->do_ident_check(this, 0, Group_check::CHECK_COLUMN); | |
| 10693 | } | ||
| 10694 | |||
| 10695 | /** | ||
| 10696 | The aim here is to find a real_item() which is of type Item_field. | ||
| 10697 | */ | ||
| 10698 | 23 | bool Item_ref::repoint_const_outer_ref(uchar *arg) { | |
| 10699 | 23 | *(pointer_cast<bool *>(arg)) = true; | |
| 10700 | 23 | return false; | |
| 10701 | } | ||
| 10702 | |||
| 10703 | /** | ||
| 10704 | If this object is the real_item of an Item_ref, repoint the result_field to | ||
| 10705 | field. | ||
| 10706 | */ | ||
| 10707 | 508 | bool Item_field::repoint_const_outer_ref(uchar *arg) { | |
| 10708 | 508 | bool *is_outer_ref = pointer_cast<bool *>(arg); | |
| 10709 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 508 times.
|
508 | if (*is_outer_ref) result_field = field; |
| 10710 | 508 | *is_outer_ref = false; | |
| 10711 | 508 | return false; | |
| 10712 | } | ||
| 10713 | |||
| 10714 | /** | ||
| 10715 | Generated fields don't need db/table names. Strip them off as inplace ALTER | ||
| 10716 | can reallocate them, making pointers invalid. | ||
| 10717 | */ | ||
| 10718 | 92306 | bool Item_field::strip_db_table_name_processor(uchar *) { | |
| 10719 | 92306 | db_name = nullptr; | |
| 10720 | 92306 | table_name = nullptr; | |
| 10721 | 92306 | return false; | |
| 10722 | } | ||
| 10723 | |||
| 10724 | 19109 | string ItemToString(const Item *item) { | |
| 10725 |
3/4✓ Branch 0 taken 123 times.
✓ Branch 1 taken 18986 times.
✓ Branch 2 taken 123 times.
✗ Branch 3 not taken.
|
19109 | if (item == nullptr) return "(none)"; |
| 10726 | 18986 | String str; | |
| 10727 |
1/2✓ Branch 0 taken 18986 times.
✗ Branch 1 not taken.
|
18986 | const ulonglong save_bits = current_thd->variables.option_bits; |
| 10728 |
1/2✓ Branch 0 taken 18986 times.
✗ Branch 1 not taken.
|
18986 | current_thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE; |
| 10729 | 37972 | item->print( | |
| 10730 |
2/4✓ Branch 0 taken 18986 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18986 times.
✗ Branch 3 not taken.
|
18986 | current_thd, &str, |
| 10731 | enum_query_type(QT_NO_DEFAULT_DB | QT_SUBSELECT_AS_ONLY_SELECT_NUMBER)); | ||
| 10732 |
1/2✓ Branch 0 taken 18986 times.
✗ Branch 1 not taken.
|
18986 | current_thd->variables.option_bits = save_bits; |
| 10733 |
1/2✓ Branch 0 taken 18986 times.
✗ Branch 1 not taken.
|
18986 | return to_string(str); |
| 10734 | 18986 | } | |
| 10735 | |||
| 10736 | 256 | Item_field *FindEqualField(Item_field *item_field, table_map reachable_tables, | |
| 10737 | bool replace, bool *found) { | ||
| 10738 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 168 times.
|
256 | if (item_field->item_equal_all_join_nests == nullptr) { |
| 10739 | 88 | *found = false; | |
| 10740 | 88 | return item_field; | |
| 10741 | } | ||
| 10742 | |||
| 10743 | // We have established in | ||
| 10744 | // 'Item_func_eq::ensure_multi_equality_fields_are_available' that this | ||
| 10745 | // item references a field that is outside of our reach. We also have a | ||
| 10746 | // multi-equality (item_equal_all_join_nests is set), so we go through all | ||
| 10747 | // fields in the multi-equality and find the first that is within our reach. | ||
| 10748 | // The table_map provided in 'reachable_tables' defines the tables within our | ||
| 10749 | // reach. | ||
| 10750 | 168 | for (Item_field &other_item_field : | |
| 10751 |
5/8✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 414 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 372 times.
✓ Branch 7 taken 42 times.
|
582 | item_field->item_equal_all_join_nests->get_fields()) { |
| 10752 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 204 times.
|
372 | if (other_item_field.field == item_field->field) { |
| 10753 | 168 | continue; | |
| 10754 | } | ||
| 10755 | |||
| 10756 |
1/2✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
|
204 | table_map item_field_used_tables = other_item_field.used_tables(); |
| 10757 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 78 times.
|
204 | if ((item_field_used_tables & reachable_tables) == item_field_used_tables) { |
| 10758 | 126 | *found = true; | |
| 10759 |
2/2✓ Branch 0 taken 117 times.
✓ Branch 1 taken 9 times.
|
126 | if (replace) { |
| 10760 |
3/6✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 117 times.
✗ Branch 5 not taken.
|
117 | Item_field *new_item_field = new Item_field(current_thd, item_field); |
| 10761 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | new_item_field->reset_field(other_item_field.field); |
| 10762 | 126 | return new_item_field; | |
| 10763 | } else { | ||
| 10764 | 9 | return item_field; | |
| 10765 | } | ||
| 10766 | } | ||
| 10767 | } | ||
| 10768 | 42 | *found = false; | |
| 10769 | 42 | return item_field; | |
| 10770 | } | ||
| 10771 | |||
| 10772 | 710730 | bool Item_asterisk::itemize(Parse_context *pc, Item **res) { | |
| 10773 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 710730 times.
|
710730 | assert(pc->select->parsing_place == CTX_SELECT_LIST); |
| 10774 | |||
| 10775 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 710730 times.
|
710730 | if (skip_itemize(res)) { |
| 10776 | ✗ | return false; | |
| 10777 | } | ||
| 10778 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 710733 times.
|
710730 | if (super::itemize(pc, res)) { |
| 10779 | ✗ | return true; | |
| 10780 | } | ||
| 10781 | 710733 | pc->select->with_wild++; | |
| 10782 | 710733 | return false; | |
| 10783 | } | ||
| 10784 | |||
| 10785 | 412121 | bool ItemsAreEqual(const Item *a, const Item *b, bool binary_cmp) { | |
| 10786 | 412121 | const Item *real_a = a->real_item(); | |
| 10787 | 412121 | const Item *real_b = b->real_item(); | |
| 10788 | |||
| 10789 | // Unwrap caches, as they may not be added consistently | ||
| 10790 | // to both sides. | ||
| 10791 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 412121 times.
|
412121 | if (real_a->type() == Item::CACHE_ITEM) { |
| 10792 | ✗ | real_a = down_cast<const Item_cache *>(real_a)->get_example(); | |
| 10793 | } | ||
| 10794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 412121 times.
|
412121 | if (real_b->type() == Item::CACHE_ITEM) { |
| 10795 | ✗ | real_b = down_cast<const Item_cache *>(real_b)->get_example(); | |
| 10796 | } | ||
| 10797 | 412121 | return real_a->eq(real_b, binary_cmp); | |
| 10798 | } | ||
| 10799 | |||
| 10800 | 245652 | bool AllItemsAreEqual(const Item *const *a, const Item *const *b, int num_items, | |
| 10801 | bool binary_cmp) { | ||
| 10802 |
2/2✓ Branch 0 taken 410550 times.
✓ Branch 1 taken 175009 times.
|
585559 | for (int i = 0; i < num_items; ++i) { |
| 10803 |
2/2✓ Branch 0 taken 70643 times.
✓ Branch 1 taken 339907 times.
|
410550 | if (!ItemsAreEqual(a[i], b[i], binary_cmp)) { |
| 10804 | 70643 | return false; | |
| 10805 | } | ||
| 10806 | } | ||
| 10807 | 175009 | return true; | |
| 10808 | } | ||
| 10809 |